【问题标题】:Problems with relative import and Python 3相对导入和 Python 3 的问题
【发布时间】:2019-01-03 19:07:51
【问题描述】:

首先,我需要描述我正在写作的环境。我正在编写将由在 CAD 应用程序中运行的 Python 运行时加载和执行的 Python 代码。 CAD 应用程序使用 Python 作为其脚本引擎。因此,我无法访问 Python 运行时,并且作为所有其他脚本的好公民,不应该修改任何系统设置。我的脚本只是加载并运行的众多脚本之一。

这一切都很好,除非我想使用非标准库。在这种情况下,我需要安装库的本地副本以供我的脚本访问。我遇到的问题是大多数库都希望安装并添加到 sys 路径中,这是我不应该做的事情,因为它可能会与其他脚本正在执行的操作产生冲突。我正在尝试做的是设置库的本地副本,然后编辑它们的源,以便它们的导入是相对的并且它们不依赖于 sys 路径。这样我的程序将拥有自己的本地库副本,而不依赖于任何其他内容,也不会干扰任何其他脚本。

我正在使用 PIP 的 -t 选项将 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: No module named 'OpenSSL'”,第二行出现“ImportError: No module named 'cryptography'”。我相当确定路径是正确的,因为如果我更改点数,我会得到 no module named 错误,但它列出了它尝试加载的内容的完整路径,而不仅仅是模块的名称。

我希望能在这个特定问题上提供一些帮助,但也可以就如何设置和使用库的私有副本提供一些总体建议。请记住,我的程序只是系统正在加载的众多程序之一,更改系统或设置虚拟环境不是一种选择。

【问题讨论】:

  • 这听起来像是一场绝对的噩梦......其他人应该如何维护它?
  • 我不相信“设置虚拟环境不是一种选择”。这正是您应该在这里做的事情,如果您完全可以写入您的用户空间,那么它一个选项。
  • 我的程序是由 CAD 系统加载的,所以我没有设置虚拟环境的选项,但希望我错了,可以做到。你对维护是正确的。这是一场噩梦,但我没有看到任何其他选择。
  • 虚拟环境本身是一个单独的文件夹,其中包含所有站点包等,并且易于维护。它与其他 Python 环境隔离,不会与其他系统包产生任何冲突。设置 docker 容器是另一种选择,我认为这是最好的选择,如果可以在您的环境中设置一个。
  • 这是什么 CAD 应用程序?

标签: python python-import importerror


【解决方案1】:

查看localimport 模块,它似乎是您特定用例的解决方案。来自自述文件:

鉴于您的 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. 有一个包装脚本(将由 CAD 软件加载),它会按照自述文件中的说明执行 localimport,然后对您的模块进行相对导入。如果您的模块足够大,可以将其放入自己的包中并以与其他所有内容相同的方式使用它(只需在 with localimport(): ... 的正文中执行 from RequestsTest import *
  3. 尝试在您编写的源代码与在 CAD Python 运行时上下文中使用该源代码所需的最终组织文件集之间建立清晰的界限。可以有一个构建/打包步骤来创建localimport 脚本、下载所需的包等。甚至更好,因为它是自动化的,而不是手动完成的事情,将来有人可能不得不重新创建。

【讨论】:

  • 这似乎可行,尽管它改变了我最初的要求,即不改变系统的任何内容。只是在这种情况下,我完成后正在管理和清理系统路径。
猜你喜欢
  • 2021-06-25
  • 2021-04-05
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 2014-11-10
相关资源
最近更新 更多