Модуль Python
Есть ли способ заставить модуль python загружать dll в директорию моего приложения, а не версию, которая пришла с установкой python, без внесения изменений в установку python (что затем потребовало бы, чтобы я сделал установщик, и будьте осторожны, я не сделал ') сломать другие приложения для людей, переписав модули python и изменив версии dll глобально...)?
В частности, я бы хотел, чтобы python использовал мою версию sqlite3.dll, а не версию, поставляемую с python (она более старая и не имеет модуля fts3).
6 ответов
Хорошо, это означает, что python всегда загружает dll в тот же каталог, что и файл pyd, независимо от того, какие пути python и os установлены.
Поэтому мне нужно было скопировать _sqlite3.pyd из python/v2.5/DLLS в каталог моих приложений, где находится новый файл sqlite3.dll, чтобы он загружал мою новую dll, а не ту, которая поставляется с python (так как файлы pyd кажутся следовать за PYTHONPATH, даже если сам актер не делает этого).
Если вы говорите о библиотеках модулей Python, то просто измените sys.path
все должно быть в порядке. Однако, если вы говорите о DLL, связанных с этими DLL; то есть libfoo.dll
который foo.pyd
зависит, то вам нужно изменить переменную окружения PATH. Я писал об этом для PyGTK некоторое время назад, но в вашем случае я думаю, что это должно быть так просто:
import os
os.environ['PATH'] = 'my-app-dir' + os.pathsep + os.environ['PATH']
Что вставлю my-app-dir
во главе вашего пути Windows, который, я считаю, также контролирует порядок загрузки для DLL.
Имейте в виду, что вам нужно будет сделать это перед загрузкой рассматриваемой DLL, т. Е. Перед импортом чего-либо интересного.
sqlite3 может быть чем-то особенным, так как он распространяется с Python; это довольно сложно проверить это быстро, поэтому я не проверял sqlite3.dll
в частности.
Ответ с модификацией
os.environ['PATH']
правильно, но у меня это не сработало, потому что я использую python 3.9. Тем не менее я получал сообщение об ошибке:
ImportError: Ошибка загрузки DLL при импорте модуля X: указанный модуль не найден.
Оказалось, что начиная с версии python 3.8 они добавили механизм, чтобы сделать это более безопасно. Прочтите документацию по
os.add_dll_directory
https://docs.python.org/3/library/os.html#os.add_dll_directory
В частности, см. Что нового в python 3.8:
Зависимости DLL для модулей расширения и DLL, загружаемых ctypes в Windows, теперь разрешаются более безопасно. На предмет зависимостей во время загрузки ищутся только системные пути, каталог, содержащий файл DLL или PYD, и каталоги, добавленные с помощью add_dll_directory(). В частности, PATH и текущий рабочий каталог больше не используются, и их изменения больше не будут влиять на нормальное разрешение DLL. Если ваше приложение использует эти механизмы, вы должны проверить add_dll_directory() и, если он существует, использовать его для добавления каталога DLL при загрузке библиотеки.
Итак, теперь это новый способ заставить его работать в Python 3.8 и новее:
import os
os.add_dll_directory('my-app-dir')
Опять же, старый способ все еще верен, и вам придется использовать его в python 3.7 и старше:
import os
os.environ['PATH'] = 'my-app-dir' + os.pathsep + os.environ['PATH']
После этого мой модуль с зависимостью dll был успешно загружен.
Я столкнулся с той же проблемой для моего.pyd
это зависит от cuda/cudnn/tensorrt.
Я пришел с небольшой функцией, которую я вызываю перед импортом моего модуля.
def add_cuda_to_path():
if os.name != "nt":
return
path = os.getenv("PATH")
if not path:
return
path_split = path.split(";")
for folder in path_split:
if "cuda" in folder.lower() or "tensorrt" in folder.lower():
os.add_dll_directory(folder)
Это самый простой обходной путь, который я нашел, поэтому мне не нужно жестко указывать какой-либо путь. Я предполагаю, что небольшое улучшение могло бы на самом деле проверить.dll
файл, но этот фрагмент хорошо подходит для моих нужд.
Тогда вы можете просто:
add_cuda_to_path()
import my_module_that_depends_on_cuda
Если ваша версия sqlite находится в sys.path до системной версии, она будет использовать это. Таким образом, вы можете поместить его в текущий каталог или изменить PYTHONPATH
переменная окружения, чтобы сделать это.
У меня была та же проблема, что и права администратора на библиотеку Python по умолчанию, заблокированные в корпоративной среде, и выполнение установки крайне затруднительно.
Что мне подходит:
- Дублируйте библиотеку sqlite3 в новом месте
- Вставьте последнюю версию sqlite3.dll (версию, которую вы хотите получить из sqlite3 web) и старый _sqlite3.pyd в новое место или новую библиотеку sqlite3. Старый _sqlite3.pyd можно найти в папке lib / DLLs библиотеки Python по умолчанию.
- Перейдите в новую библиотеку sqlite3 и измените dbapi2.py следующим образом: Измените "с _sqlite3 import *" на "from sqlite3._sqlite3 import *"
- Убедитесь, что python сначала загружает эту новую библиотеку sqlite3. При необходимости добавьте путь к этой библиотеке.