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

/Foo
    bar.py
    spam.py
    eggs.py

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


当前回答

注意你的__init__.py定义了__all__。模块-包文档说

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later. ... The only solution is for the package author to provide an explicit index of the package. The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered. It is up to the package author to keep this list up-to-date when a new version of the package is released. Package authors may also decide not to support it, if they don’t see a use for importing * from their package. For example, the file sounds/effects/__init__.py could contain the following code: __all__ = ["echo", "surround", "reverse"] This would mean that from sound.effects import * would import the three named submodules of the sound package.

其他回答

这是我迄今为止发现的最好的方法:

from os.path import dirname, join, isdir, abspath, basename
from glob import glob
pwd = dirname(__file__)
for x in glob(join(pwd, '*.py')):
    if not x.startswith('__'):
        __import__(basename(x)[:-3], globals(), locals())

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

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

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

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导入*不是一个好主意,有几个原因,包括名称冲突,使其难以分析代码。

将__all__变量添加到__init__.py,包含:

__all__ = ["bar", "spam", "eggs"]

参见http://docs.python.org/tutorial/modules.html

何时从。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是为了避免在已经导入模块时重新导入模块,因为这可能存在循环导入的风险。