Поддержка OS.symlink в окнах
Я загрузил python 2.7.1 с веб-сайта python и установил его в Windows. При попытке symlink файла я обнаружил, что он не поддерживается.
Однако я нашел эту проблему и увидел, что он исправлен. Будет ли это реализовано, и если да, то когда? Я запускаю Windows Vista.
Ответы
Ответ 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