简体   繁体   English

是否可以从 Python 包中导入单个模块?

[英]Is it possible to import a single module from a Python package?

I have a python package called utils .我有一个名为utils的 python 包。 It consists of a few modules, and an __init__.py file tying them all together.它由几个模块和一个将它们捆绑在一起的__init__.py文件组成。

__init__.py:
    from .modA import util1
    from .modB import util2
    from .modC import util3

modA.py:
    def util1():
        print("Util 1")

modB.py:
    import flask               # <-- Note this import
    def util2():
        print("Util 2")

modC.py:
    def util3():
        print("Util 3")

When the software is running that imports this package, it's running in a virtual environment that has flask installed, so everything works fine.当导入这个包的软件运行时,它运行在一个安装了烧瓶的虚拟环境中,所以一切正常。

The problem I'm having is that if I interactively run python in my shell, and do something like from utils.modC import util3 , even though modC has absolutely no reliance on modB, and doesn't import, or use flask, I'm still going to get an error that modB couldn't import flask (assuming I didn't activate the virtual environment in my shell first).我遇到的问题是,如果我在 shell 中以交互方式运行python ,并执行类似from utils.modC import util3 ,即使 modC 绝对不依赖 modB,并且不导入或使用烧瓶,我我仍然会得到一个错误,modB 无法导入 Flask(假设我没有先在我的 shell 中激活虚拟环境)。

$ python3
Python 3.9.0 (default, Oct 27 2020, 14:15:17) 
[Clang 12.0.0 (clang-1200.0.32.21)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from utils.modC import util3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/USERNAME/test/utils/__init__.py", line 2, in <module>
    from .modB import util2
  File "/Users/USERNAME/test/utils/modB.py", line 1, in <module>
    import flask
ModuleNotFoundError: No module named 'flask'

Without modifying the source code of the package, is there any way for me to import util3 without having flask in my sys.path (AKA without it trying to import everything listed in __init__.py )?在不修改包的源代码的情况下,有什么方法可以让我导入util3而我的sys.path flask没有flask (也就是没有尝试导入__init__.py列出的所有内容)?

Failing that, is there any simple way to modify __init__.py to allow this?否则,是否有任何简单的方法可以修改__init__.py以允许这样做?

As kaspersky pointed out here , you can do it in a dirty way:正如卡巴斯基在这里指出的,你可以用一种肮脏的方式来做到这一点:

>>> import sys
>>> sys.path.append("utils")
>>> from modC import util3
>>> util3()
Util 3

Or use the PYTHONPATH env variable to modify sys.path indirectly.或者使用 PYTHONPATH 环境变量间接修改sys.path

This works because when you run from modC import util3 , Python will start looking through sys.path for a module or package named modC , which is different than when we ran from utils.modC import util3 , where it was looking for a module or package named utils .这是有效的,因为当你from modC import util3运行时,Python 将开始通过sys.path查找名为modC的模块或包,这与我们from utils.modC import util3运行时不同,它在那里寻找模块或包名为utils Appending the string utils to sys.path tells it to look there as a last resort, and because there are no other places it will find modC , it will eventually find it there and load it as a module, rather than a package.将字符串utils附加到sys.path告诉它作为最后的手段查看那里,因为没有其他地方它会找到modC ,它最终会在那里找到它并将其作为模块而不是包加载。

This apparently won't work in some cases, but works for me.这在某些情况下显然不起作用,但对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM