Модуль 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 по умолчанию, заблокированные в корпоративной среде, и выполнение установки крайне затруднительно.

Что мне подходит:

  1. Дублируйте библиотеку sqlite3 в новом месте
  2. Вставьте последнюю версию sqlite3.dll (версию, которую вы хотите получить из sqlite3 web) и старый _sqlite3.pyd в новое место или новую библиотеку sqlite3. Старый _sqlite3.pyd можно найти в папке lib / DLLs библиотеки Python по умолчанию.
  3. Перейдите в новую библиотеку sqlite3 и измените dbapi2.py следующим образом: Измените "с _sqlite3 import *" на "from sqlite3._sqlite3 import *"
  4. Убедитесь, что python сначала загружает эту новую библиотеку sqlite3. При необходимости добавьте путь к этой библиотеке.
Другие вопросы по тегам