有人能为我提供一个导入整个模块目录的好方法吗? 我有一个这样的结构:
/Foo
bar.py
spam.py
eggs.py
我尝试通过添加__init__.py并从Foo import *将其转换为一个包,但它没有按我希望的方式工作。
有人能为我提供一个导入整个模块目录的好方法吗? 我有一个这样的结构:
/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.
其他回答
我自己也厌倦了这个问题,所以我写了一个名为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安全的。
尼尔
将__all__变量添加到__init__.py,包含:
__all__ = ["bar", "spam", "eggs"]
参见http://docs.python.org/tutorial/modules.html
这是我迄今为止发现的最好的方法:
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())
我想补充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')]
扩展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'>