Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python &引用;从src导入*”;包或子包中所有函数的动态导入_Python_Python 3.x_Import_Python Import_Importerror - Fatal编程技术网

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

  • 假设src import*中的
    不是最具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)