2011-06-07 113 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