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

/Foo
    bar.py
    spam.py
    eggs.py

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


当前回答

我已经为此创建了一个模块,它不依赖于__init__.py(或任何其他辅助文件),并让我只输入以下两行:

import importdir
importdir.do("Foo", globals())

请随意重用或贡献:http://gitlab.com/aurelien-lourot/importdir

其他回答

Anurag Uniyal给出了改进建议!

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import os
import glob

all_list = list()
for f in glob.glob(os.path.dirname(__file__)+"/*.py"):
    if os.path.isfile(f) and not os.path.basename(f).startswith('_'):
        all_list.append(os.path.basename(f)[:-3])

__all__ = all_list  

我想补充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 *不够好,这是对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是为了避免在已经导入模块时重新导入模块,因为这可能存在循环导入的风险。

扩展Mihail的回答,我认为非黑客的方式(即不直接处理文件路径)如下:

在Foo/下创建一个空的__init__.py文件 执行

import pkgutil
import sys


def load_all_modules_from_dir(dirname):
    for importer, package_name, _ in pkgutil.iter_modules([dirname]):
        full_package_name = '%s.%s' % (dirname, package_name)
        if full_package_name not in sys.modules:
            module = importer.find_module(package_name
                        ).load_module(full_package_name)
            print module


load_all_modules_from_dir('Foo')

你会得到:

<module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
<module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
  __import__(module)