使用Python将所有模块加载到文件夹中

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

/Foo bar.py spam.py eggs.py 

我试着把它转换成一个包,通过添加__init__.pyfrom Foo import *但它没有按照我所希望的方式工作。

__all__variables添加到__init__.py其中包含:

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

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

列出当前文件夹中的所有python( .py )文件,并将它们作为__all__variables放在__init__.py

 from os.path import dirname, basename, isfile import glob modules = glob.glob(dirname(__file__)+"/*.py") __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] 

更新:今天你可能想用importlib来代替。

通过添加一个__init__.py使Foo目录成为一个包。 在这__init__.py添加:

 import bar import eggs import spam 

既然你想dynamic的(这可能也可能不是一个好主意),列出所有的py文件列表目录和导入他们这样的东西:

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

扩展Mihail的答案,我相信这个非hackish的方式(如,不直接处理文件path)如下:

  1. Foo/下创build一个空的__init__.py文件,
  2. 执行
 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'> 

Python,包括一个目录下的所有文件:

对于那些不能上class的新手而言,

  1. 创build一个文件夹/ home / el / foo并在/ home / el / foo下创build一个文件main.py把这个代码放在那里:

     from hellokitty import * spam.spamfunc() ham.hamfunc() 
  2. build立一个目录/home/el/foo/hellokitty

  3. /home/el/foo/hellokitty下创build一个文件__init__.py ,并把这个代码放在那里:

     __all__ = ["spam", "ham"] 
  4. /home/el/foo/hellokitty下创build两个python文件: spam.pyham.py

  5. 在spam.py中定义一个函数:

     def spamfunc(): print "Spammity spam" 
  6. 在ham.py中定义一个函数:

     def hamfunc(): print "Upgrade from baloney" 
  7. 运行:

     el@apollo:/home/el/foo$ python main.py spammity spam Upgrade from baloney 

我自己已经厌倦了这个问题,所以我写了一个名为automodinit的包来修复它。 你可以从http://pypi.python.org/pypi/automodinit/得到它。;

用法如下所示:

  1. automodinit包纳入setup.py依赖关系。
  2. 把所有的__init__.py文件replace成这样:
 __all__ = [“我将被重写”]
 #不要修改上面的行或这一行!
导入automodinit
 automodinit.automodinit(__ name__,__file__,globals())
 del automodinit
 #任何你想要的东西都可以在这里之后去,它不会被修改。

而已! 从现在开始,导入模块会将__all__设置为模块中的.py [co]文件列表,并且还将导入每个文件,就好像您input了:

 for x in __all__: import x 

因此,“从M导入*”的效果恰好与“导入M”匹配。

automodinit很高兴从ZIP档案里面运行,因此ZIP是安全的。

尼尔

我也遇到了这个问题,这是我的解决scheme:

 import os def loadImports(path): files = os.listdir(path) imps = [] for i in range(len(files)): name = files[i].split('.') if len(name) > 1: if name[1] == 'py' and name[0] != '__init__': name = name[0] imps.append(name) file = open(path+'__init__.py','w') toWrite = '__all__ = '+str(imps) file.write(toWrite) file.close() 

该函数创build一个名为__init__.py的文件(在提供的文件夹中),其中包含一个__all__variables,用于保存文件夹中的每个模块。

例如,我有一个名为Test的文件夹,其中包含:

 Foo.py Bar.py 

所以在脚本中,我想要将模块导入到我将写入:

 loadImports('Test/') from Test import * 

这将导入Test所有内容, Test__init__.py文件现在包含:

 __all__ = ['Foo','Bar'] 

Anurag Uniyal回答build议的改进!

 #!/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的例子有几个更正:

 import os, glob modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py")) __all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")] 

看到你的__init__.py定义了__all__ 。 模块 – 包 doc说

需要使用__init__.py文件来使Python将目录视为包含包; 这是为了防止具有通用名称的目录(如string)无意中隐藏稍后在模块searchpath中发生的有效模块。 在最简单的情况下, __init__.py可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__variables,稍后介绍。

唯一的解决scheme是软件包作者提供一个明确的软件包索引。 import语句使用以下约定:如果某个包的__init__.py代码定义了一个名为__all__的列表,则将其视为遇到包import *时应导入的模块名列表。 当软件包的新版本发布时,软件包作者应该保持这个列表是最新的。 软件包作者也可能决定不支持它,如果他们没有看到从包中导入*的用法。 例如,文件sounds/effects/__init__.py可能包含以下代码:

__all__ = ["echo", "surround", "reverse"]

这意味着from sound.effects import *会导入声音包的三个命名的子模块。

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

 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()) 

我知道我正在更新一个相当古老的post,我尝试使用automodinit ,但发现它的设置过程是打破了python3。 所以,基于卢卡的回答,我想出了一个更简单的答案 – 这可能不适用于.zip – 这个问题,所以我想我应该在这里分享:

在你的yourpackage__init__.py模块中:

 #!/usr/bin/env python import os, pkgutil __all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.split(__file__)[0]) 

并在您的包装下的另一个包装内:

 from yourpackage import * 

然后你将所有放在包中的模块加载,如果你写了一个新的模块,它也会被自动导入。 当然,谨慎使用这种事情,大国有很大的责任。

 import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'): __import__(module) 

查看标准库中的pkgutil模块。 只要你在目录中有一个__init__.py文件,它就可以让你做你想要的东西。 __init__.py文件可以是空的。

我创build了一个模块,它不依赖于__init__.py . __init__.py (或任何其他辅助文件),并使我只键入以下两行:

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

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