Поддержка OS.symlink в Windows - PullRequest
       17

Поддержка OS.symlink в Windows

19 голосов
/ 07 июня 2011

Я скачал python 2.7.1 с сайта python и установил его в windows. При попытке создать символическую ссылку на файл я обнаружил, что он не поддерживается.

Однако я обнаружил эту проблему и увидел, что она исправлена. Будет ли это реализовано, и если да, то когда? Я использую Windows Vista.

Ответы [ 3 ]

27 голосов
/ 11 декабря 2011

Есть способ исправить это, исправив модуль os при запуске вашей среды Python.

Функция создания символических ссылок уже доступна из Windows API, вам нужно только вызвать ее.

Во время запуска python предпринимается попытка импортировать модуль с именем sitecustomize.py в каталог site-packages .Мы будем использовать эту ловушку для присоединения нашей функции к модулю 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, она понадобится каждой программе, которая утверждает, что использует этот API Windows.Это можно сделать, запустив ваш интерпретатор Python с повышенными правами cmd.exe.Лучшей альтернативой является предоставление привилегии пользователю при условии, что ваша редакция Windows поставляется с необходимым редактором групповой политики (gpedit.msc).Смотрите скриншот ниже.Вы можете изменить это значение, чтобы включить любого пользователя или группу безопасности, требующих такого рода привилегий, без ущерба для безопасности административных учетных записей.

The group policy editor

Примечание: Фрагмент кода из здесь

20 голосов
/ 23 февраля 2013

Как и ответ Фернандо Маседо, но ИМО менее инвазивен:

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()
10 голосов
/ 07 февраля 2015

Как и Джан Марко Герарди ответ , но определяет 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

Если вы запускаете ваш скрипт как администратор, все в порядке, если вы хотите запустить его как пользователь - вы должны предоставить python разрешение на создание символических ссылок - что возможно только в Windows Vista + Ultimate или профессиональный.

Редактировать

Джан Марко Герарди ответ создает ссылку на путь 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 в Windows. Но использование этой утилиты требует таких же разрешений. Тем не менее:

# 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 :

Вот что я, наконец, использую: этот скрипт создает ссылку под окнами, если у пользователя есть на это полномочия, в противном случае он просто не создает ссылку:

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
...