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

/Foo
    bar.py
    spam.py
    eggs.py

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


当前回答

我有一个嵌套的目录结构,即在包含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)

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

其他回答

看看标准库中的pkgutil模块。只要目录中有__init__.py文件,它就会让你做你想做的事情。__init__.py文件可以为空。

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

2017年更新:你可能想用importlib代替。

通过添加__init__.py使Foo目录成为一个包。在__init__.py中添加:

import bar
import eggs
import spam

因为你希望它是动态的(这可能是也可能不是一个好主意),用list dir列出所有的py-files,然后像这样导入它们:

import os
for module in os.listdir(os.path.dirname(__file__)):
    if module == '__init__.py' or module[-3:] != '.py':
        continue
    __import__(module[:-3], locals(), globals())
del module

然后,从你的代码这样做:

import Foo

您现在可以使用

Foo.bar
Foo.eggs
Foo.spam

从Foo导入*不是一个好主意,有几个原因,包括名称冲突,使其难以分析代码。

使用importlib,唯一需要添加的是

from importlib import import_module
from pathlib import Path

__all__ = [
    import_module(f".{f.stem}", __package__)
    for f in Path(__file__).parent.glob("*.py")
    if "__" not in f.stem
]
del import_module, Path

列出当前文件夹中的所有python (.py)文件,并将它们作为__init__.py中的__all__变量

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