首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >转换POSIX->WIN路径,在Cygwin Python中,不调用cygpath

转换POSIX->WIN路径,在Cygwin Python中,不调用cygpath
EN

Stack Overflow用户
提问于 2012-06-04 23:56:44
回答 4查看 4.5K关注 0票数 14

我使用在Python的Cygwin版本中运行的Python脚本来创建向本机Windows实用程序(不支持Cygwin)发出的命令。这需要在发出命令之前将路径参数从POSIX转换为WIN格式。

调用cygpath实用程序是最好的方式,因为它使用Cygwin来做它应该做的事情,但它也有点可怕(而且很慢)。

我已经在运行Python的Cygwin版本了--所以提供了进行转换的代码。似乎应该有一个Cygwin/Python特定的扩展,让我可以直接在Python中使用这个功能,而不必启动一个全新的进程。

EN

回答 4

Stack Overflow用户

发布于 2016-07-20 11:46:56

这可以通过使用ctype调用Cygwin API来实现。以下代码适用于我-我在Windows 2012上使用64位cygwin DLL版本2.5.2,这适用于Python 2.7.10和Python 3.4.3的Cygwin版本。

基本上,我们从cygwin1.dll调用cygwin_create_path来执行路径转换。该函数分配包含已转换路径的内存缓冲区(使用malloc)。因此,我们需要从cygwin1.dll使用free来释放它分配的缓冲区。

请注意,下面的xunicodesix (Python2/3兼容性库)的替代方案;如果您需要同时支持Python2和Python3,six是更好的答案,但我希望我的示例不依赖于任何非捆绑模块,这就是为什么我这样做的原因。

代码语言:javascript
复制
from ctypes import cdll, c_void_p, c_int32, cast, c_char_p, c_wchar_p
from sys import version_info

xunicode = str if version_info[0] > 2 else eval("unicode")

# If running under Cygwin Python, just use DLL name
# If running under non-Cygwin Windows Python, use full path to cygwin1.dll
# Note Python and cygwin1.dll must match bitness (i.e. 32-bit Python must
# use 32-bit cygwin1.dll, 64-bit Python must use 64-bit cygwin1.dll.)
cygwin = cdll.LoadLibrary("cygwin1.dll")
cygwin_create_path = cygwin.cygwin_create_path
cygwin_create_path.restype = c_void_p
cygwin_create_path.argtypes = [c_int32, c_void_p]

# Initialise the cygwin DLL. This step should only be done if using
# non-Cygwin Python. If you are using Cygwin Python don't do this because
# it has already been done for you.
cygwin_dll_init = cygwin.cygwin_dll_init
cygwin_dll_init.restype = None
cygwin_dll_init.argtypes = []
cygwin_dll_init()

free = cygwin.free
free.restype = None
free.argtypes = [c_void_p]

CCP_POSIX_TO_WIN_A = 0
CCP_POSIX_TO_WIN_W = 1
CCP_WIN_A_TO_POSIX = 2
CCP_WIN_W_TO_POSIX = 3

def win2posix(path):
    """Convert a Windows path to a Cygwin path"""
    result = cygwin_create_path(CCP_WIN_W_TO_POSIX,xunicode(path))
    if result is None:
        raise Exception("cygwin_create_path failed")
    value = cast(result,c_char_p).value
    free(result)
    return value

def posix2win(path):
    """Convert a Cygwin path to a Windows path"""
    result = cygwin_create_path(CCP_POSIX_TO_WIN_W,str(path))
    if result is None:
        raise Exception("cygwin_create_path failed")
    value = cast(result,c_wchar_p).value
    free(result)
    return value

# Example, convert LOCALAPPDATA to cygwin path and back
from os import environ
localAppData = environ["LOCALAPPDATA"]
print("Original Win32 path: %s" % localAppData)
localAppData = win2posix(localAppData)
print("As a POSIX path: %s" % localAppData)
localAppData = posix2win(localAppData)
print("Back to a Windows path: %s" % localAppData)
票数 5
EN

Stack Overflow用户

发布于 2012-06-05 03:46:53

从浏览cygpath source来看,cygpath似乎有一个不平凡的实现,并且没有提供任何库版本。

cygpath支持使用-f选项从文件中获取输入(或使用-f -从标准输入中获取输入),并且可以采用多个路径,每次都会生成一个转换后的路径,因此您可能会创建一个打开的cygpath实例(使用Python的subprocess.Popen),而不是每次都重新启动cygpath。

票数 1
EN

Stack Overflow用户

发布于 2017-03-24 19:02:31

我宁愿写这个使用cygwin动态链接库的Python helper:

代码语言:javascript
复制
import errno
import ctypes
import enum
import sys

class ccp_what(enum.Enum):
    posix_to_win_a = 0 # from is char *posix, to is char *win32
    posix_to_win_w = 1 # from is char *posix, to is wchar_t *win32
    win_a_to_posix = 2 # from is char *win32, to is char *posix
    win_w_to_posix = 3 # from is wchar_t *win32, to is char *posix

    convtype_mask = 3

    absolute = 0          # Request absolute path (default).
    relative = 0x100      # Request to keep path relative.
    proc_cygdrive = 0x200 # Request to return /proc/cygdrive path (only with CCP_*_TO_POSIX)

class CygpathError(Exception):
    def __init__(self, errno, msg=""):
        self.errno = errno
        super(Exception, self).__init__(os.strerror(errno))

class Cygpath(object):
    bufsize = 512

    def __init__(self):
        if 'cygwin' not in sys.platform:
            raise SystemError('Not running on cygwin')

        self._dll = ctypes.cdll.LoadLibrary("cygwin1.dll")

    def _cygwin_conv_path(self, what, path, size = None):
        if size is None:
            size = self.bufsize
        out = ctypes.create_string_buffer(size)
        ret = self._dll.cygwin_conv_path(what, path, out, size)
        if ret < 0:
            raise CygpathError(ctypes.get_errno())
        return out.value

    def posix2win(self, path, relative=False):
        out = ctypes.create_string_buffer(self.bufsize)
        t = ccp_what.relative.value if relative else ccp_what.absolute.value
        what = ccp_what.posix_to_win_a.value | t
        return self._cygwin_conv_path(what, path)

    def win2posix(self, path, relative=False):
        out = ctypes.create_string_buffer(self.bufsize)
        t = ccp_what.relative.value if relative else ccp_what.absolute.value
        what = ccp_what.win_a_to_posix.value | t
        return self._cygwin_conv_path(what, path)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10884268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档