Windows中的OS.symlink支持

时间:2011-06-07 02:42:43

标签: windows-vista python-2.7

我从python网站下载了python 2.7.1并将其安装到了windows。在尝试对文件进行符号链接时,我发现它不受支持。

然而,我找到this issue,并看到它已修复。这会被实施,如果是这样的话?我正在运行Windows Vista。

3 个答案:

答案 0 :(得分:26)

有一种方法可以解决这个问题,在你的python环境启动时修补 os 模块。

创建符号链接的功能已经可以从Windows API获得,您只需要调用它。

在python启动期间,尝试在site-packages directory上导入名为 sitecustomize.py 的模块。我们将使用此钩子将我们的函数附加到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

的代码段

答案 1 :(得分:20)

就像Fernando Macedo的回答一样,但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()

答案 2 :(得分:10)

与Gian Marco Gherardi answer一样,但在Windows上定义os.symlink,以便您的代码可以安全地在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下使用。

修改

Gian Marco 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

另一种方法是使用window的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下创建一个链接,否则它就不会建立链接:

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