2012-06-04 7 views
10

मैं मूल विंडोज उपयोगिताओं (सिगविन-जागरूक नहीं) को जारी किए गए आदेश बनाने के लिए पाइथन के सिग्विन बिल्ड में चल रहे एक पायथन स्क्रिप्ट का उपयोग करता हूं। कमांड जारी करने से पहले इसे पॉज़िक्स से WIN फॉर्म में पथ पैरामीटर के रूपांतरण की आवश्यकता होती है।सिग्विन पायथन में, PINIX-> WIN पथ कनवर्ट करें, w/o कॉलिंग cygpath

साइगपाथ उपयोगिता को कॉल करना ऐसा करने का सबसे अच्छा तरीका है, क्योंकि यह ऐसा करने के लिए सिगविन का उपयोग करता है, लेकिन यह थोड़ा डरावना (और धीमा) भी है।

मैं पहले ही पाइथन का एक सिग्विन निर्माण चला रहा हूं - इसलिए रूपांतरण करने के लिए कोड मौजूद है। ऐसा लगता है कि एक सिग्विन/पायथन विशिष्ट एक्सटेंशन होना चाहिए जो मुझे पूरी क्षमता को आग लगाने के बिना सीधे पाइथन में इस क्षमता के लिए एक हुक देता है।

उत्तर

1

cygpath source ब्राउज़ करने से, ऐसा लगता है कि साइगपाथ का एक अनौपचारिक कार्यान्वयन है और कोई लाइब्रेरी संस्करण उपलब्ध नहीं है।

cygpath समर्थन -f विकल्प का उपयोग करने के लिए फ़ाइल से अपने इनपुट लेने (या stdin से, -f - का प्रयोग करके) और कई रास्तों ले जा सकते हैं, एक परिवर्तित मार्ग हर बार बाहर थूकना करता है, तो आप शायद एक भी cygpath उदाहरण खुला बना सकते हैं (प्रत्येक बार साइगपाथ को पुनरारंभ करने के बजाय पाइथन के subprocess.Popen का उपयोग करना)।

3

साइटीविन एपीआई को ctypes का उपयोग करके कॉल करना संभव है। नीचे दिया गया कोड मेरे लिए काम करता है- मैं विंडोज 2012 पर 64-बिट सिग्विन डीएलएल संस्करण 2.5.2 का उपयोग कर रहा हूं, और यह पायथन 2.7.10 और पायथन 3.4.3 दोनों के सिग्विन संस्करणों पर काम करता है।

असल में हम पथ रूपांतरण करने के लिए cygwin1.dll से cygwin_create_path कहते हैं। यही कारण है कि समारोह एक स्मृति बफर (malloc का प्रयोग करके) परिवर्तित मार्ग से युक्त आवंटित करता है। तो हमें आवंटित बफर को रिहा करने के लिए cygwin1.dll से free का उपयोग करने की आवश्यकता है।

नोट करें कि xunicode नीचे six (एक पायथन 2/3 संगतता लाइब्रेरी) के लिए एक गरीब व्यक्ति का विकल्प है; यदि आप दोनों अजगर 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) 
+0

ctypes-कोड बांटने के लिए धन्यवाद, लेकिन मैं इसे WinPython-3.5.2 और 2.7 के साथ चलने नहीं कर सकता। 10: ctypes '' self._handle = _dlopen (self._name, मोड) '' पर PY2 क्रैश, और '' परिणाम = cygwin_create_path (CCP_WIN_W_TO_POSIX, xunicode (पथ)) OSError पर PY3: अपवाद: पहुँच उल्लंघन 0x0000000000000000'' लिखना। कोई विचार? – ankostis

+0

@ankostis, मुझे लगता है कि समस्या लाइन 'cygwin = cdll.LoadLibrary (" cygwin1.dll ")' में होने की संभावना है। सिग्विन पायथन के साथ, 'cygwin1.dll' पहले ही पाइथन प्रक्रिया पता स्थान में लोड हो चुका है, इसलिए' लोड लाइब्रेरी 'को इसे खोजने में कोई परेशानी नहीं है। हालांकि, WinPython के बाद से एक शुद्ध विंडोज अनुप्रयोग (कोई cygwin), तो 'cygwin1.dll' सामान्य रूप से, लोड नहीं किया जाएगा ताकि आप अपने' cygwin1.dll' का पूर्ण पथ प्रदान करने की आवश्यकता है। साथ ही, यदि आपका WinPython 64-बिट है, तो आपको 64-बिट 'cygwin1.dll' लोड करने की आवश्यकता है; इसके विपरीत, यदि आपका WinPython 32-बिट है, तो आपको 32-बिट 'cygwin1.dll' लोड करने की आवश्यकता है। –

+0

मैंने कहा कि मैंने एक और मशीन में कोशिश की है, और अब मुझे यह मिल रहा है: 'मूल Win32 पथ: सी: \ उपयोगकर्ता \ ankostis \ AppData \ स्थानीय 0 [मुख्य] ​​पायथन 772 डी: \ Apps \ WinPython-64bit- 3.5.2.1 \ अजगर-3.5.2.amd64 \ अजगर।exe: *** घातक त्रुटि - आंतरिक त्रुटि: TP_NUM_C_BUFS बहुत छोटा: 50 1090 [मुख्य] ​​पायथन 772 cygwin_exception :: open_stackdumpfile: python.exe.stackdump @tokoti (cygwin): ~/work/gitdb पर डंपिंग स्टैक ट्रेस। git $ less python.exe.stackdump' – ankostis

0

मैं नहीं बल्कि इस अजगर सहायक cygwin dll का उपयोग करता है लिखते थे:

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) 
संबंधित मुद्दे