2011-06-07 61 views
18

我從python網站下載了python 2.7.1,並將它安裝到了windows。嘗試符號鏈接文件時,我發現它不受支持。Windows中的OS.symlink支持

但是,我發現this issue,並看到它是固定的。這是否會實施,如果是的話?我正在運行Windows Vista。

+0

嘗試Python 3.2。 – Blender 2011-06-07 02:53:20

+0

添加作爲答案,我會標記爲正確的。 – xaav 2011-06-07 14:58:24

+0

@xaav,因爲Blender的答案已被刪除(我不知道爲什麼),您能否認可我的答案,將其標記爲正確,因爲它顯示了問題的解決方法?謝謝! – 2014-12-18 14:04:38

回答

24

有一種方法可以解決這個問題,在您的python環境啓動時修補模塊os

創建符號鏈接的功能已經可以從Windows API獲得,您只需要調用它即可。

在python的啓動過程中,嘗試導入名爲sitecustomize.py的模塊,在site-packages directory上。我們將使用這個鉤子將我們的功能附加到os模塊。

將這個代碼的文件sitecustomize.py:

import os 

__CSL = None 
def symlink(source, link_name): 
    '''symlink(source, link_name) 
     Creates a symbolic link pointing to source named link_name''' 
    global __CSL 
    if __CSL is None: 
     import ctypes 
     csl = ctypes.windll.kernel32.CreateSymbolicLinkW 
     csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 
     csl.restype = ctypes.c_ubyte 
     __CSL = csl 
    flags = 0 
    if source is not None and os.path.isdir(source): 
     flags = 1 
    if __CSL(link_name, source, flags) == 0: 
     raise ctypes.WinError() 

os.symlink = symlink 

你的Python過程中需要啓用「創建符號鏈接」特權啓動,這是不是一個Python的問題,每一個程序,聲稱使用這個Windows API將需要它。這可以通過從提升的cmd.exe運行Python解釋器來完成。如果Windows版本附帶所需的組策略編輯器(gpedit.msc),則更好的選擇是授予用戶特權。請參閱下面的截圖。您可以調整該值以包含任何用戶或安全組需要這種權限而不會影響管理帳戶的安全性。

The group policy editor

注:代碼從here

+0

儘管權限設置爲我的最佳知識(用戶是管理員,腳本以非提升模式運行),但我仍然收到權限錯誤。可能是什麼原因? – eudoxos 2012-11-06 20:16:08

+0

@eudoxos您的python進程需要以管理員權限啓動。這可以通過從提升的cmd.exe運行它來完成。 – 2012-11-21 13:11:35

+1

我已經在網絡上的某個地方找到了它。這是完全愚蠢的,一個管理員必須啓動自己的進程提升它的工作。由於它是一個用戶程序,我不能要求用戶在提升模式下運行它。 Microsoft安全設計。 – eudoxos 2012-11-22 09:47:46

20

像費爾南多·馬塞答案片斷,但IMO創傷小:

def symlink(source, link_name): 
    import os 
    os_symlink = getattr(os, "symlink", None) 
    if callable(os_symlink): 
     os_symlink(source, link_name) 
    else: 
     import ctypes 
     csl = ctypes.windll.kernel32.CreateSymbolicLinkW 
     csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 
     csl.restype = ctypes.c_ubyte 
     flags = 1 if os.path.isdir(source) else 0 
     if csl(link_name, source, flags) == 0: 
      raise ctypes.WinError() 
9

像吉安·馬爾科GHERARDI answer但定義os.symlink在Windows上,以便您的代碼可以安全地在Windows和Linux上工作:

import os 
os_symlink = getattr(os, "symlink", None) 
if callable(os_symlink): 
    pass 
else: 
    def symlink_ms(source, link_name): 
     import ctypes 
     csl = ctypes.windll.kernel32.CreateSymbolicLinkW 
     csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 
     csl.restype = ctypes.c_ubyte 
     flags = 1 if os.path.isdir(source) else 0 
     if csl(link_name, source, flags) == 0: 
      raise ctypes.WinError() 
    os.symlink = symlink_ms 

如果你以管理員身份運行你的腳本,一切都很好,如果你想以用戶身份運行它 - 你必須要grant python a permission to make symlinks - 這隻能在windows vista + ultimate或professional下運行。

編輯

吉安·馬爾科GHERARDI answer創建一個鏈接到一個UNIX路徑:like/this和它不工作。解決方法是做source.replace('/', '\\')

# symlink support under windows: 
import os 
os_symlink = getattr(os, "symlink", None) 
if callable(os_symlink): 
    pass 
else: 
    def symlink_ms(source, link_name): 
     import ctypes 
     csl = ctypes.windll.kernel32.CreateSymbolicLinkW 
     csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 
     csl.restype = ctypes.c_ubyte 
     flags = 1 if os.path.isdir(source) else 0 
     if csl(link_name, source.replace('/', '\\'), flags) == 0: 
      raise ctypes.WinError() 
    os.symlink = symlink_ms 

另一種方法是使用窗口的Vista + mklink效用。但使用此實用程序需要相同的權限。靜像:

# symlink support under windows: 
import os 
os_symlink = getattr(os, "symlink", None) 
if callable(os_symlink): 
    pass 
else: 
    def symlink_ms(source, link_name): 
     os.system("mklink {link} {target}".format(
      link = link_name, 
      target = source.replace('/', '\\'))) 
    os.symlink = symlink_ms 

編輯2

這裏就是我終於用:這樣的腳本可以在Windows下一個鏈接,如果用戶有privilage這樣做,否則它只是沒有一個鏈接:

import os 
if os.name == "nt": 
    def symlink_ms(source, link_name): 
     import ctypes 
     csl = ctypes.windll.kernel32.CreateSymbolicLinkW 
     csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 
     csl.restype = ctypes.c_ubyte 
     flags = 1 if os.path.isdir(source) else 0 
     try: 
      if csl(link_name, source.replace('/', '\\'), flags) == 0: 
       raise ctypes.WinError() 
     except: 
      pass 
    os.symlink = symlink_ms 
+0

我明白如果遇到權限問題,該函數被設計爲noop,但我不明白爲什麼ctypes.WinError異常會被引發,如果它總是被異常處理程序吞下?這是一個佔位符,使開發人員可以選擇與異常做不同的事情,還是我在這裏錯過了一個微妙的東西? – 2016-08-16 15:27:01

+0

@WilliamPayne:據我所知,它是由於它具有足夠的權限而產生鏈接,但是在'csl(link_name,source.replace('/','\\'),flags)= = 0' - 在這種情況下,它也會建立鏈接。所以一切正常,我不明白爲什麼'WinError'。所以我只是壓制了這個錯誤。 – Adobe 2016-08-16 15:43:47