有人能为我提供一个导入整个模块目录的好方法吗? 我有一个这样的结构:
/Foo
bar.py
spam.py
eggs.py
我尝试通过添加__init__.py并从Foo import *将其转换为一个包,但它没有按我希望的方式工作。
有人能为我提供一个导入整个模块目录的好方法吗? 我有一个这样的结构:
/Foo
bar.py
spam.py
eggs.py
我尝试通过添加__init__.py并从Foo import *将其转换为一个包,但它没有按我希望的方式工作。
当前回答
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导入*不是一个好主意,有几个原因,包括名称冲突,使其难以分析代码。
其他回答
何时从。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是为了避免在已经导入模块时重新导入模块,因为这可能存在循环导入的风险。
我知道我正在更新一个相当旧的帖子,我尝试使用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 *
然后,您将加载包中放置的所有模块,如果您编写了一个新模块,它也将被自动导入。当然,要小心使用这些东西,能力越大责任越大。
注意你的__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())
列出当前文件夹中的所有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')]