Esto es posible llamando a la API de Cygwin utilizando ctypes. El siguiente código funciona para mí: estoy usando la versión 2.5.2 de cygwin de 64 bits en Windows 2012, y esto funciona en las versiones de Cygwin de Python 2.7.10 y Python 3.4.3.
Básicamente llamamos cygwin_create_path
desde cygwin1.dll
para realizar la conversión de ruta. Esa función asigna un búfer de memoria (usando malloc
) que contiene la ruta convertida. Entonces, necesitamos usar free
desde cygwin1.dll
para liberar el búfer que asignó.
Tenga en cuenta que xunicode
a continuación es una alternativa pobre a six (una biblioteca de compatibilidad Python 2/3); si necesita admitir Python 2 y 3, seis es la respuesta mucho mejor, pero quería que mi ejemplo no tuviese dependencias en ningún módulo no incluido, por eso lo hice de esta manera.
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)
Gracias por compartir la ctypes de código, pero no puedo hacer que se ejecute con WinPython-3.5.2 y 2.7. 10: accidentes AP2 en ctypes '' self._handle = _dlopen (self._name, modo) '', y AP3 en '' resultado = cygwin_create_path (CCP_WIN_W_TO_POSIX, xunicode (ruta de acceso)) OSError: excepción: violación de acceso escribiendo 0x0000000000000000''. ¿Algunas ideas? – ankostis
@ankostis, creo que el problema es probable en la línea 'cygwin = cdll.LoadLibrary (" cygwin1.dll ")'. Con Cygwin Python, 'cygwin1.dll' ya está cargado en el espacio de direcciones del proceso de Python para que' LoadLibrary' no tenga problemas para encontrarlo. Sin embargo, dado que WinPython es una aplicación pura de Windows (no Cygwin), por lo que 'cygwin1.dll' normalmente no se cargará, por lo que debe proporcionar la ruta completa a su' cygwin1.dll'. Además, si su WinPython es de 64 bits, debe cargar un 'cygwin1.dll' de 64 bits; por el contrario, si su WinPython es de 32 bits, debe cargar un 'cygwin1.dll' de 32 bits. –
Intenté en otra máquina como dijiste, y ahora estoy obteniendo esto: 'Ruta Win32 original: C: \ Users \ ankostis \ AppData \ Local 0 [principal] python 772 D: \ Apps \ WinPython-64bit- 3.5.2.1 \ python-3.5.2.amd64 \ python.exe: *** error fatal - Error interno: TP_NUM_C_BUFS demasiado pequeño: 50 1090 [main] python 772 cygwin_exception :: open_stackdumpfile: volcado de la pila de rastreo a python.exe.stackdump @tokoti (cygwin): ~/Work/gitdb. git $ less python.exe.stackdump' – ankostis