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

jrm*_*063 12 python cygwin

我使用Python脚本,在Python的Cygwin构建中运行,以创建发布到本机Windows实用程序的命令(不支持Cygwin).这需要在发出命令之前将路径参数从POSIX转换为WIN形式.

调用cygpath实用程序是最好的方法,因为它使用Cygwin来做它在那里做的事情,但它也有点可怕(而且很慢).

我已经在运行Python的Cygwin构建 - 所以存在进行转换的代码.似乎应该有一个Cygwin/Python特定的扩展,直接在Python中为我提供了这个功能的钩子,而不必启动一个全新的过程.

Sim*_*ane 5

这可以通过使用ctypes调用Cygwin API来实现。以下代码对我有用—我在Windows 2012上使用64位cygwin DLL 2.5.2版,并且在Python 2.7.10和Python 3.4.3的Cygwin版本上均适用。

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

请注意,xunicode以下是穷人的替代方案(六个 Python 2/3兼容性库);如果您需要同时支持Python 2和3,那么六个是更好的答案,但是我希望我的示例不依赖任何非捆绑模块,这就是我这样做的原因。

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)
Run Code Online (Sandbox Code Playgroud)


Jos*_*ley 1

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

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