Windows中的OS.symlink支持

xaa*_*aav 19 windows-vista python-2.7

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

但是,我发现了这个问题,并发现它已修复.这会被实施,如果是这样的话?我正在运行Windows Vista.

Fer*_*edo 26

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

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

在python启动期间,尝试在site-packages目录中导入名为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
Run Code Online (Sandbox Code Playgroud)

您的Python进程需要以启用"创建符号链接"权限启动,这不是Python问题,声称使用此Windows API的每个程序都需要它.这可以通过提升运行Python解释器来完成cmd.exe.如果Windows版附带了必需的组策略编辑器(gpedit.msc),则更好的选择是将权限授予用户.请参见下面的截图.您可以调整该值以包括任何用户或安全组需要此类权限,而不会影响管理帐户的安全性.

组策略编辑器

注意:此处的代码段

  • 对于一些模糊的(至少对我来说)安全原因,Microsoft enginneer决定允许仅为"管理员"组的成员创建符号链接.可以使用"本地安全策略"工具("创建符号链接"选项)更改此设置.不幸的是,由于UAC,这对管理员组中的用户不起作用:http://social.technet.microsoft.com/Forums/en-US/itprovistasecurity/thread/cb593ad0-9edc-4cd1-bb67-46c360b45f91 (3认同)

Gia*_*rdi 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()
Run Code Online (Sandbox Code Playgroud)


Ado*_*obe 10

就像Gian Marco Gherardi的答案,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
Run Code Online (Sandbox Code Playgroud)

如果你以管理员身份运行你的脚本一切都很好,如果你想以用户身份运行它 - 你必须授予python一个制作符号链接的权限 - 这只能在windows vista + ultimate或professional下使用.

编辑:

Gian Marco Gherardi 回答创建了一个指向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
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用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
Run Code Online (Sandbox Code Playgroud)

编辑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
Run Code Online (Sandbox Code Playgroud)