如何在Python中单独导入一个子模块?

5

I have this structure:

.
└── module
    ├── __init__.py
    └── submodule
        ├── __init__.py
        ├── foo.py
        └── bar.py

module.submodule.__init__.py文件中,我有以下内容:
import foo
import bar

module.submodule.foo.py中,我有这样一个代码块:
import very_heavy_third_party_module as vhtpm
...

我只想导入bar,但是我被foo拖慢了(假设foomodule/__init__.py中都有一个丑陋的time.sleep(3))。
因此,我的目标是在不受模块其他部分影响的情况下编写以下内容:
from module.submodule.bar import saybar
saybar()

我该如何仅导入位于我的子模块bar中的saybar


1
从模块导入子模块.bar.saybar? - Illusionist
@Illusionist 不是真的有效。 你尝试过 from datetime import datetime.now 吗? - nowox
我不知道这是否可行,但看起来 bar 不属于那个子模块。 - imreal
1
你不能这样做。为了导入子模块,你必须先导入它所在的包。如果在定义包的 __init__.py 文件中导入了所有子模块,那么你总是会导入所有的子模块,而且你无法避免这种情况。要解决这个问题:避免将导入语句放在 __init__.py 中,或者只导入那些速度较快的模块,不导入耗时的模块。 - Bakuriu
1
sys.path.append(r'path_to_module\module\submodule');import bar ???sys.path.append(r'path_to_module\module\submodule');import bar ??? - Skycc
1个回答

3
只有一种方法可以在不运行foo的情况下从bar中导入,那就是从module.submodule.__init__.py中删除import foo。因为当你在 Python 中导入一个包/模块时,该模块的所有顶级代码(或者如果导入一个包,则是__init__.py)都会被运行。当你运行from module.submodule.bar import saybar时,它会运行以下所有顶级代码:
  • module.__init__.py
  • module.submodule.__init__.py
  • module.submodule.bar.py
由于module.submodule.__init__.py包含import foo,所以foo也被导入并且它的所有顶级代码(包括import very_heavy_third_party_module as vhtpm)也被运行,导致减速。
一些可能的解决方案是:
  • 尽可能将代码移出__init__.py。通常的做法是让__init__.py为空——如果里面有一些功能性代码,你可能要考虑将其移动到自己的模块中。一旦只剩下import行,你可以删除它们,因为它们对名称空间没有影响。
  • foo.py中的import vhtpm移到顶级之下(例如进入由模块中其他东西调用的函数)。这不是很干净,但如果你需要优化,可能适合你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接