假设我在各自的.py文件中分别拥有ClassA,ClassB和ClassC,这些文件分别称为ClassA.py
,ClassB.py
和ClassC.py
。
# Inside ClassA.py
class ClassA:
pass
在我的__init__.py
中,我最终以
from .ClassA import ClassA
from .ClassB import ClassB
from .ClassC import ClassC
每次添加一个新类(使用相同的结构)时,都必须更改__init__.py
。鉴于此包中的所有文件都遵循相同的结构(不是相当的pythonic-but-oh-well),有没有建议的自动化方法?
答案 0 :(得分:2)
这是可能,但不推荐。
请考虑以下目录结构:
├── test_module
│ ├── ClassA.py
│ ├── ClassB.py
│ └── __init__.py
我们希望以编程方式将ClassA.ClassA
和ClassB.ClassB
导入__init__.py
。
假设这些是ClassA.py
的内容:
class ClassA:
pass
ClassB.py
是相同的,除了class
的名称。
现在,假设在__init__.py
中,我们想以非递归方式遍历根目录(由于没有目录,所以没关系),并从其中的所有模块导入所有classes
。
__init__.py
:
import os
from importlib import import_module
my_location = os.path.dirname(__file__)
module_list = [file
for file in os.listdir(my_location)
if os.path.splitext(file)[1] == '.py'
and file != '__init__.py']
modules = [import_module(f'.{os.path.splitext(module)[0]}', __name__)
for module in module_list]
运行import test_module
之后,来自classes
和ClassA.py
的{{1}}将分别以ClassB.py
和test_module.ClassA.ClassA
的形式导入工作名称空间。
说明:
test_module.ClassB.ClassB
出于完整性考虑,如果您希望此脚本模仿>>> import test_module
>>> test_module.ClassA.ClassA()
<test_module.ClassA.ClassA object at 0x7f1e66181fd0>
的行为:
from X import Y
导入:
globals().update({name: getattr(module, name)
for module in modules
for name in module.__dict__
if not name.startswith('_')})
这些将使这些名称可以用>>> import test_module
>>> test_module.ClassA()
<test_module.ClassA.ClassA object at 0x7fb8edb9dfd0>
等访问(因为您是从 test_module.ClassA
导入的,所以我们添加了一个间接层。在test_module
中的范围,可以直接使用无限定名称来访问它们。
我们还可以添加其他功能,例如检查每个模块的test_module
属性并执行子目录的递归遍历,但这超出了这个问题的范围,我必须强调我的想法是,最好重构您的代码,这样一来就不需要,而不是强加于似乎不太强大的Python内部功能>必不可少。
答案 1 :(得分:1)
是的,可以。这就是importlib包的用途。它包含实际执行导入的较低级别的调用。它使您可以通过调用提供的方法来进行导入。
因此,您可以使用Python os.path.listdir
或其他方法来学习子包,然后调用importlib
来导入每个子包。
我本人并没有做太多事情。足以知道这个存在。也许其他人可以给您更多细节。另外,此链接可能对您有所帮助:
https://dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805