Ciò è possibile chiamando l'API Cygwin utilizzando i tipi. Il codice seguente funziona per me: sto usando la versione 2.5.2 Cygwin DLL a 64 bit su Windows 2012, e questo funziona sulle versioni Cygwin sia di Python 2.7.10 che di Python 3.4.3.
In pratica si chiama cygwin_create_path
da cygwin1.dll
per eseguire la conversione del percorso. Quella funzione alloca un buffer di memoria (usando malloc
) contenente il percorso convertito. Quindi, è necessario utilizzare free
da cygwin1.dll
per rilasciare il buffer assegnato.
Nota che xunicode
è un'alternativa di scarsa qualità a six (una libreria di compatibilità Python 2/3); se hai bisogno di supportare sia Python 2 e 3, sei è la risposta molto migliore, ma volevo che il mio esempio fosse libero da dipendenze su qualsiasi modulo non raggruppato ed è per questo che l'ho fatto in questo modo.
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)
fonte
2016-07-20 03:46:56
Grazie per aver condiviso il ctypes-code, ma non riesco a farlo funzionare con WinPython-3.5.2 e 2.7. 10: PY2 si blocca su ctypes '' self._handle = _dlopen (self._name, mode) '', e PY3 su '' risultato = cygwin_create_path (CCP_WIN_W_TO_POSIX, xunicode (percorso)) OSError: eccezione: violazione di accesso scrivendo 0x0000000000000000''. Qualche idea? – ankostis
@ankostis, penso che il problema sia probabilmente alla riga 'cygwin = cdll.LoadLibrary (" cygwin1.dll ")'. Con Cygwin Python, 'cygwin1.dll' è già stato caricato nello spazio di indirizzamento del processo Python quindi' LoadLibrary' non ha problemi a trovarlo. Tuttavia, dal momento che WinPython è una pura app per Windows (senza Cygwin), quindi 'cygwin1.dll' non verrà normalmente caricato, quindi è necessario fornire il percorso completo al tuo' cygwin1.dll'. Inoltre, se il tuo WinPython è a 64 bit, devi caricare un 'cygwin1.dll 'a 64 bit; viceversa, se il tuo WinPython è a 32 bit, devi caricare un 'cygwin1.dll 'a 32 bit. –
Ho provato in un'altra macchina come hai detto, e ora sto ottenendo questo: 'Percorso originale Win32: C: \ Users \ ankostis \ AppData \ Local 0 [main] python 772 D: \ Apps \ WinPython-64bit- 3.5.2.1 \ python-3.5.2.amd64 \ python.exe: *** errore fatale - Errore interno: TP_NUM_C_BUFS troppo piccolo: 50 1090 [main] python 772 cygwin_exception :: open_stackdumpfile: scarica la traccia di stack in python.exe.stackdump @tokoti (cygwin): ~/Work/gitdb. git $ less python.exe.stackdump' – ankostis