我有一个目录结构如下:
| main.py
| scripts
|--| __init__.py
| script1.py
| script2.py
| script3.py
从main.py
导入模块scripts
。我尝试将pkgutils.walk_packages
与__all__
结合使用,但使用这种方法,我只能使用from scripts import *
直接导入main
下的所有子模块。我想把它们都放在scripts
下。导入scripts
的所有子模块以便从main
访问scripts.script1
的最干净的方法是什么?
答:对不起,我有点含糊。我想在运行时导入子模块,而不在__init__.py
中显式指定它们。我可以使用pkgutils.walk_packages
来获取子模块名称(除非有人知道更好的方法),但我不确定使用这些名称的最干净的方法(或者walk_packages
返回的Importors?)来导入它们。
9条答案
按热度按时间yrefmtwq1#
**编辑:**这里有一种在运行时递归导入所有内容的方法...
(顶部软件包目录中
__init__.py
的内容)我在这里没有使用
__import__(__path__+'.'+module_name)
,因为使用它很难正确地递归导入包。如果您没有嵌套的子包,并且希望避免使用globals()[module_name]
,那么这是一种方法。可能有更好的办法,但这是我能做的最好的了。
原始答案(对于上下文,忽略其他内容。我最初误解了这个问题):
你的
scripts/__init__.py
是什么样子的?它应该是这样的:您甚至可以不定义
__all__
,但是如果您定义了它,即使它只是您导入的内容的一个列表,事情(如果没有其他东西的话,pydoc)也会更干净地工作。vulvrdjw2#
这是基于the answer that kolypto provided,但他的答案不执行包的递归导入,而这是。虽然主问题没有要求,但我相信递归导入适用,并且在许多类似的情况下非常有用。我是在搜索这个主题时发现这个问题的。
这是一种很好的、干净的子包模块导入方式,并且应该是可移植的,它使用了python2.7 + / 3.x的标准库。
try:results[full_name] = importlib.import_module(full_name)and except ModuleNotFoundError:继续
用法:
osh3o9ms3#
简单地工作,并允许在包内相对导入:
用途:
jtw3ybtb4#
没有我想要的那么干净,但是没有一种更干净的方法对我有用。这实现了指定的行为:
目录结构:
其中
pkg/scripts/__init__.py
为空,pkg/__init__.py
包含:虽然很乱,但应该是便携式的。我已经在几个不同的包中使用了这段代码。
yruzcnhs5#
我自己也厌倦了这个问题,所以我写了一个名为automodinit的包来解决它。你可以从http://pypi.python.org/pypi/automodinit/得到它。用法是这样的:
1.将automodinit包包含到
setup.py
依赖项中。1.将以下内容添加到
__init__.py
文件的开头:就是这样!从现在开始,导入模块将把
__all__
设置为模块中的.py[co]文件列表,并且还将导入这些文件中的每一个,就像您输入的一样:因此,
from M import *
的效果与import M
完全匹配。automodinit很高兴从内部ZIP档案运行,因此是ZIP安全的。
ua4mk5z46#
要只 * 加载 * 一个包的所有子模块,你可以使用这个简单的函数:
用例:加载Flask应用程序的所有数据库模型,以便Flask-Migrate可以检测到模式的更改。用途:
gjmwrych7#
我正在编写一个小型的个人库,并一直在添加新的模块,所以我编写了一个shell脚本来查找脚本并创建
__init__.py
的。该脚本在我的包pylux的主目录外执行。我知道这可能不是你想要的答案,但它为我服务了它的目的,它可能对其他人也有用。
zed5wv108#
我尝试过Joe Kington's Answer,并构建了一个使用
globals
和get/setattr
的解决方案,因此不需要eval。一个小小的修改是,我没有直接使用walk_packages
的包__path__
,而是使用包的父目录,然后只导入以__name__ + "."
开头的模块。这样做是为了可靠地从walk_packages
中获取所有子包-在我的用例中,我有一个名为test
的子包,这导致pkgutil从python的库中迭代test
包;此外,使用__path__
不会递归到packages子目录。所有这些问题都是使用jython和python2.5观察到的,下面的代码到目前为止只在jython中测试过。还要注意的是,OP的问题只讨论了从一个包中导入所有 * 模块 *,这段代码也递归地导入了所有包。
作为未来的改进,我将尝试在包上添加一个
__getattr__
钩子来使其动态化,这样实际的模块只有在访问时才被导入……x6492ojm9#
这在Python 3.3中很好用。请注意,这只适用于与
__init__.py
位于同一目录的子模块。但是,通过一些工作,它也可以增强对目录中子模块的支持。