Python &引用;从src导入*”;包或子包中所有函数的动态导入
目标:Python &引用;从src导入*”;包或子包中所有函数的动态导入,python,python-3.x,import,python-import,importerror,Python,Python 3.x,Import,Python Import,Importerror,目标: 我希望能够通过“直接调用”动态导入子包中的所有函数 用法: 我的项目: project/ |-- main.py |-- src/ |---- __init__.py |---- foo.py |---- bar.py foo.py只有一个功能: def foo_funct(): print("foo") def bar_funct(): print("bar") bar.py只有一个功能: def foo_funct(): print("foo")
我希望能够通过“直接调用”动态导入子包中的所有函数 用法:
我的项目:
project/
|-- main.py
|-- src/
|---- __init__.py
|---- foo.py
|---- bar.py
foo.py
只有一个功能:
def foo_funct():
print("foo")
def bar_funct():
print("bar")
bar.py
只有一个功能:
def foo_funct():
print("foo")
def bar_funct():
print("bar")
最后是main.py
:
from src import *
(...)
foo_funct()
bar_funct()
(...)
评论:
\uuuu init\uuuuu.py
是这样的
import os
__all__ = [i.replace(".py", "") for i in os.listdir(os.getcwd()+"/src/") if "__" not in i]
我将能够调用foo.foo\u funct()
或bar.bar\u funct()
,但不能调用foo\u funct()
或bar\u funct()
\uuuu init\uuuu.py
是这样的:
from src.foo import *
from src.bar import *
我将能够调用foo\u funct()
或bar\u funct()
,但对于每个新的子包,我必须修改我的\uu init\uuuuuuuuy.py
不是最具python风格的方法,并且假设由于可能的命名冲突(例如a.tree\u funct()
和b.tree\u funct()
)而直接调用可能非常危险,有什么方法可以达到我的目标吗
就我个人而言,我更喜欢保持事情的明确性,只需将作为包API一部分的名称显式导入
\uuuu init\uuuu
。您的项目不会变化太快,因此动态地将所有内容导入\uuuu init\uuuuuuuuy.py
将节省时间
但是如果你想这样做,那么你有几个选择。如果您需要支持早于3.7的Python版本,那么可以通过点击。列出所有.py
文件,并使用导入它们(如果需要支持2.7之前的Python版本,也可以使用):
上述方法保持了名称空间的整洁;运行\u load\u all\u submodules()
函数后,会将其从包中删除。它使用\uu文件\uu
全局来确定当前路径,并从中查找任何同级.py
文件
如果您只需要支持Python3.7及更高版本,则可以定义以实现动态查找
在包\uuuu init\uuuu.py
文件中使用这些钩子可能如下所示:
def _find_submodules():
from pathlib import Path
from importlib import import_module
package_path = Path(__file__).resolve().parent
return tuple(p.stem for p in package_path.glob('*.py') if p.stem != '__init__')
__submodules__ = _find_submodules()
del _find_submodules
def __dir__():
from importlib import import_module
names = []
for module_name in __submodules__:
module = import_module(f'.{module_name}', __package__)
try:
names += module.__all__
except AttributeError:
names += (n for n in dir(module) if n[:1] != '_')
return sorted(names)
__all__ = __dir__()
def __getattr__(name):
from importlib import import_module
for module_name in __submodules__:
module = import_module(f'.{module_name}', __package__)
try:
# cache the attribute so future imports don't call __getattr__ again
obj = getattr(module, name)
globals()[name] = obj
return obj
except AttributeError:
pass
raise AttributeError(name)