Проблемы с относительным импортом и Python 3 - PullRequest
0 голосов
/ 03 января 2019

Во-первых, мне нужно описать среду, для которой я пишу.Я пишу код Python, который будет загружаться и выполняться в среде исполнения Python, работающей в приложении CAD.Приложение САПР использует Python в качестве скриптового движка.В результате у меня нет доступа к среде исполнения Python, и я, как хороший гражданин, не должен изменять никакие системные настройки.Мой скрипт - только один из многих, которые загружены и работают.

Все это прекрасно работает, кроме случаев, когда я хочу использовать нестандартные библиотеки.В этом случае мне нужно установить локальную копию библиотеки для доступа к моему сценарию.Проблема, с которой я сталкиваюсь, заключается в том, что большинство библиотек ожидают установки и добавления к пути sys, чего я не должен делать, потому что это может создать конфликты с тем, что делают другие скрипты.Вместо этого я пытаюсь установить локальную копию библиотек и затем отредактировать их источник, чтобы их импорт был относительным и не зависел от пути sys.Таким образом, моя программа будет иметь свою собственную локальную копию библиотек и не будет зависеть ни от чего и не будет мешать другим скриптам.

Я использую опцию -t PIP для установки Requests и PyOpenSSL ввложенная папка "Packages" в моей папке скриптов.Вот сокращенный список того, что у меня есть.

RequestsTest/
    RequestsTest.py 
    Packages/
        OpenSSL/
            cryptography/
                x509/
                    __init__.py
                    base.py
                hazmat/
                    __init__.py
                    backends/
                        __init__.py
                        interfaces.py
                        openssl/
                            __init__.py
                            backend.py
                            x509.py
            OpenSSL/
                __init__.py
                SSL.py
        Requests/
            chardet/
                __init__.py
            requests/
                __init__.py
            urllib3/
                __init__.py
                request.py
                contrib/
                    __init__.py
                    pyopenssl.py
                util/
                    __init__.py
                    request.py
                    ssl_.py

Хотя очень сложно отследить различные операторы импорта и сделать их относительными, похоже, это работает.Однако у меня возникают проблемы с одним конкретным набором импортов.

В Packages / Requests / urllib3 / contrib / pyopenssl.py он содержит следующие импорты, которые я изменил:

from ....OpenSSL.OpenSSL import SSL 
from ....OpenSSL.cryptography import x509

Первоначально они были:

from OpenSSL import OpenSSL.SSL
from cryptography import x509

Я получаю сообщение об ошибке «ImportError: нет модуля с именем« OpenSSL »» для первой строки и «ImportError: нет модуля с именем« cryptography »» для второй строки.Я совершенно уверен, что путь правильный, потому что, если я изменю количество точек, я получу сообщение об отсутствии модуля с именем error, но в нем будет указан полный путь того, что он пытается загрузить, а не только имя модуля.

Буду признателен за помощь в решении этой конкретной проблемы, но также могу воспользоваться некоторыми общими советами о том, как создавать и использовать частные копии библиотек.Помните, что моя программа - лишь одна из многих, которую система загружает, меняя систему или настраивая виртуальную среду. Это не вариант.

1 Ответ

0 голосов
/ 03 января 2019

Проверьте модуль localimport , который, кажется, является решением для вашего конкретного случая использования.Из README:

Учитывая, что ваш скрипт, приложение или плагин Python поставляется с каталогом, содержащим модули для импорта, вы можете использовать localimport для поддержания состояния глобального импортера в чистоте.

app.py
res/modules/
  some_package/
    __init__.py


# app.py
with localimport('res/modules') as _importer:
    import some_package
    assert 'some_package' not in sys.modules

Слоган «Изолированный импорт модулей Python для встроенных приложений».так что это выглядит довольно актуально.

При использовании этого модуля следующее может помочь сохранить порядок:

  1. Поместите действительную логику скрипта в отдельный файл.
  2. Имейте скрипт-обертку (который будет загружен программным обеспечением САПР), который выполняет localimport, как указано в README, затем выполняет относительный импорт вашего модуля.Если ваш модуль становится достаточно большим, возможно, поместите его в свой собственный пакет и используйте его так же, как и все остальное (просто сделайте from RequestsTest import * в теле with localimport(): ....
  3. Постарайтесь установить четкую границумежду исходным кодом, который вы пишете, и окончательным организованным набором файлов, необходимых для использования этого исходного кода в контексте среды выполнения CAD Python. Можно выполнить этап сборки / упаковки, который создает сценарий localimport, загружает необходимые пакетыи т. д. Лучше даже потому, что тогда это автоматизировано, а не то, что было сделано вручную, что кому-то в будущем, возможно, придется воссоздать.
...