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

/Foo
    bar.py
    spam.py
    eggs.py

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


当前回答

我想补充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')]

其他回答

import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
  __import__(module)

我自己也厌倦了这个问题,所以我写了一个名为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的例子有几个更正:

import os, glob

modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))
__all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")]

我知道我正在更新一个相当旧的帖子,我尝试使用automodinit,但发现它的设置过程对python3是坏的。所以,基于Luca的回答,我想出了一个更简单的答案——可能不适合。zip——来解决这个问题,所以我想我应该在这里分享它:

在你的包的__init__.py模块中:

#!/usr/bin/env python
import os, pkgutil
__all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)]))

在你的包下面的另一个包里:

from yourpackage import *

然后,您将加载包中放置的所有模块,如果您编写了一个新模块,它也将被自动导入。当然,要小心使用这些东西,能力越大责任越大。