How to load all modules in a folder?
有人能为我提供一个导入整个模块目录的好方法吗?我有这样的结构:
1 2 3 4 | /Foo bar.py spam.py eggs.py |
我试图通过添加
列出当前文件夹中的所有python(
1 2 3 4 | 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')] |
将
1 | __all__ = ["bar","spam","eggs"] |
另请参见http://docs.python.org/tutorial/modules.html
更新:今天您可能想使用
通过添加
1 2 3 | import bar import eggs import spam |
由于您希望它是动态的(这可能是一个好主意,也可能不是一个好主意),请用list dir列出所有py文件,然后用如下方式导入它们:
1 2 3 4 5 6 | 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 |
然后,根据您的代码执行以下操作:
1 | import Foo |
您现在可以使用
1 2 3 | Foo.bar Foo.eggs Foo.spam |
等等,从foo导入*不是一个好主意,原因有几个,包括名称冲突和使代码难以分析。
扩展Mihail的答案,我认为非黑客方式(如,不直接处理文件路径)如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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') |
你会得到:
1 2 | <module 'Foo.bar' from '/home/.../Foo/bar.pyc'> <module 'Foo.spam' from '/home/.../Foo/spam.pyc'> |
python,包括目录下的所有文件:
对于那些不能让它工作的新手来说,他们需要双手紧握。
创建一个文件夹/home/el/foo,并在/home/el/foo下创建一个文件
1 2 3 | from hellokitty import * spam.spamfunc() ham.hamfunc() |
制作目录
在
1 | __all__ = ["spam","ham"] |
生成两个python文件:
在spam.py中定义函数:
1 2 | def spamfunc(): print"Spammity spam" |
在ham.py中定义函数:
1 2 | def hamfunc(): print"Upgrade from baloney" |
运行它:
1 2 3 | el@apollo:/home/el/foo$ python main.py spammity spam Upgrade from baloney |
我自己也厌倦了这个问题,所以我写了一个叫做automodinit的包来解决它。您可以从http://pypi.python.org/pypi/automodinit/获得它。
用法如下:
1 2 3 4 5 6 | __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. |
就是这样!从现在起,导入模块将设置为模块中的.py[co]文件列表,还将导入每个文件在这些文件中,您好像键入了:
1 | for x in __all__: import x |
因此,"从M导入*"的效果与"导入M"完全匹配。
尼尔
我知道我正在更新一个相当老的帖子,我尝试使用
在来自
1 2 3 | #!/usr/bin/env python import os, pkgutil __all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)])) |
在
1 | from yourpackage import * |
然后,您将加载放置在包中的所有模块,如果编写一个新模块,它也将自动导入。当然,谨慎地使用这类东西,拥有强大的权力就有巨大的责任。
我也遇到了这个问题,这是我的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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() |
此函数创建一个名为
例如,我有一个名为
1 2 | Foo.py Bar.py |
因此,在脚本中,我希望将模块导入其中,我将写下:
1 2 | loadImports('Test/') from Test import * |
这将从
1 | __all__ = ['Foo','Bar'] |
Anurag Uniyal给出了建议改进的答案!
1 2 3 4 5 6 7 8 9 10 11 12 | #!/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的例子中有几个修正:
1 2 3 4 | 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")] |
1 2 3 4 | import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'): __import__(module) |
这是迄今为止我发现的最好的方法:
1 2 3 4 5 6 | 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()) |
注意你的
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 filesounds/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.
我已经为它创建了一个模块,它不依赖于
1 2 | import importdir importdir.do("Foo", globals()) |
请随意重复使用或贡献:http://gitlab.com/aurelien-lourot/importdir
从标准库中查看pkgutil模块。只要目录中有一个
只需通过importlib导入它们,并将它们添加到
1 2 3 4 5 6 7 8 9 10 11 12 | /Foo bar.py spam.py eggs.py __init__.py # __init__.py import os import importlib pyfile_extes = ['py', ] __all__ = [importlib.import_module('.%s' % filename, __package__) for filename in [os.path.splitext(i)[0] for i in os.listdir(os.path.dirname(__file__)) if os.path.splitext(i)[1] in pyfile_extes] if not filename.startswith('__')] del os, importlib, pyfile_extes |