這可以通過使用ctypes調用Cygwin API來實現。下面的代碼適用於我 - 我在Windows 2012上使用64位cygwin DLL版本2.5.2,這適用於Python 2.7.10和Python 3.4.3的Cygwin版本。
基本上我們稱cygwin_create_path
從cygwin1.dll
執行路徑轉換。該函數分配一個包含已轉換路徑的內存緩衝區(使用malloc
)。那麼我們需要使用cygwin1.dll
中的free
來釋放它分配的緩衝區。
請注意,下面的xunicode
是six(一個Python 2/3兼容庫)的替代品。如果你需要同時支持Python 2和Python 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)
感謝您分享的ctypes的代碼,但我不能使它與WinPython-3.5.2和2.7上運行。 10:上ctypes的''self._handle = _dlopen(self._name,模式)'' PY2崩潰,並且 PY3上''結果= cygwin_create_path(CCP_WIN_W_TO_POSIX,xunicode(路徑)) OSERROR:異常:訪問衝突寫入0x0000000000000000''。有任何想法嗎? – ankostis
@ankostis,我認爲這個問題可能出現在'cygwin = cdll.LoadLibrary(「cygwin1.dll」)''行。使用Cygwin Python時,'cygwin1.dll'已經加載到Python進程地址空間中,所以'LoadLibrary'沒有任何問題。然而,由於WinPython是一個純粹的Windows應用程序(沒有Cygwin),所以'cygwin1.dll'通常不會被加載,所以你需要提供'cygwin1.dll'的完整路徑。另外,如果你的WinPython是64位的,你需要加載一個64位的'cygwin1.dll';相反,如果你的WinPython是32位的,你需要加載一個32位的'cygwin1.dll'。 –
我嘗試在另一臺機器上,因爲你說,現在我得到這個: '原始Win32路徑:C:\ Users \ ankostis \ AppData \ Local 0 [main] python 772 D:\ Apps \ WinPython-64bit- 3.5.2.1 \蟒蛇,3.5.2.amd64 \蟒蛇。exe:***致命錯誤 - 內部錯誤:TP_NUM_C_BUFS太小:50 1090 [main] python 772 cygwin_exception :: open_stackdumpfile:將堆棧跟蹤轉儲到python.exe.stackdump @tokoti(cygwin):〜/ Work/gitdb。 git $ less python.exe.stackdump' – ankostis