有人能为我提供一个导入整个模块目录的好方法吗? 我有一个这样的结构:

/Foo
    bar.py
    spam.py
    eggs.py

我尝试通过添加__init__.py并从Foo import *将其转换为一个包,但它没有按我希望的方式工作。


当前回答

包含一个目录下的所有文件:

专为那些无法上手的新手准备的。

Make a folder /home/el/foo and make a file main.py under /home/el/foo Put this code in there: from hellokitty import * spam.spamfunc() ham.hamfunc() Make a directory /home/el/foo/hellokitty Make a file __init__.py under /home/el/foo/hellokitty and put this code in there: __all__ = ["spam", "ham"] Make two python files: spam.py and ham.py under /home/el/foo/hellokitty Define a function inside spam.py: def spamfunc(): print("Spammity spam") Define a function inside ham.py: def hamfunc(): print("Upgrade from baloney") Run it: el@apollo:/home/el/foo$ python main.py spammity spam Upgrade from baloney

其他回答

何时从。Import *不够好,这是对ted的回答的改进。具体来说,这种方法不需要使用__all__。

"""Import all modules that exist in the current directory."""
# Ref https://stackoverflow.com/a/60861023/
from importlib import import_module
from pathlib import Path

for f in Path(__file__).parent.glob("*.py"):
    module_name = f.stem
    if (not module_name.startswith("_")) and (module_name not in globals()):
        import_module(f".{module_name}", __package__)
    del f, module_name
del import_module, Path

请注意,globals()中没有module_name是为了避免在已经导入模块时重新导入模块,因为这可能存在循环导入的风险。

我有一个嵌套的目录结构,即在包含python模块的主目录中有多个目录。

我在__init__.py文件中添加了以下脚本以导入所有模块

import glob, re, os 

module_parent_directory = "path/to/the/directory/containing/__init__.py/file"

owd = os.getcwd()
if not owd.endswith(module_parent_directory): os.chdir(module_parent_directory)

module_paths = glob.glob("**/*.py", recursive = True)

for module_path in module_paths:
    if not re.match( ".*__init__.py$", module_path):
        import_path = module_path[:-3]
        import_path = import_path.replace("/", ".")
        exec(f"from .{import_path} import *")

os.chdir(owd)

也许这不是实现这一目标的最佳方式,但除此之外我没有别的办法。

我自己也厌倦了这个问题,所以我写了一个名为automodinit的包来解决它。你可以从http://pypi.python.org/pypi/automodinit/上得到它。

用法是这样的:

将automodinit包包含到setup.py依赖项中。 像这样替换所有__init__.py文件:

__all__ = ["I will get rewritten"]
# Don't modify the line above, or this line!
import automodinit
automodinit.automodinit(__name__, __file__, globals())
del automodinit
# Anything else you want can go after here, it won't get modified.

就是这样!从现在开始导入一个模块将设置__all__为 模块中的.py[co]文件列表,也将导入每个文件 就好像你输入了:

for x in __all__: import x

因此,“from M import *”的效果与“import M”完全匹配。

automodinit从ZIP档案内部运行,因此是ZIP安全的。

尼尔

这里有一个解决方案,您不必写文件名。只需将此代码片段添加到__init__.py中

from inspect import isclass
from pkgutil import iter_modules
from pathlib import Path
from importlib import import_module

# iterate through the modules in the current package
package_dir = Path(__file__).resolve().parent
for (_, module_name, _) in iter_modules([package_dir]):

    # import the module and iterate through its attributes
    module = import_module(f"{__name__}.{module_name}")
    for attribute_name in dir(module):
        attribute = getattr(module, attribute_name)

        if isclass(attribute):            
            # Add the class to this package's variables
            globals()[attribute_name] = attribute

我想补充Anurag Uniyal的回答。 你可以让它变得更简单,去掉大量的导入。 __init__.py文件的内容:

from os import listdir
from os.path import dirname
__all__ = [i[:-3] for i in listdir(dirname(__file__)) if not i.startswith('__') and i.endswith('.py')]