Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Есть способ исправить это, начните исправление модуля os в вашей среде python.

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

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

The group policy editor

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

Ответ 2

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

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()

Ответ 3

Как и Gian Marco Gherardi answer, но определяет os.symlink в окнах, чтобы ваш код мог безопасно работать с окнами и 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

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

Edit

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

Другой способ - использовать утилиту vista 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:

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

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