Eva*_*ark 245 python python-import
有人能为我提供一个导入整个模块目录的好方法吗?
我有这样的结构:
/Foo
bar.py
spam.py
eggs.py
Run Code Online (Sandbox Code Playgroud)
我尝试通过添加__init__.py
和执行将其转换为包,from Foo import *
但它没有按照我希望的方式工作.
Anu*_*yal 373
列出.py
当前文件夹中的所有python()文件,并将它们作为__all__
变量放入__init__.py
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')]
Run Code Online (Sandbox Code Playgroud)
ste*_*anw 127
将__all__
变量添加到__init__.py
包含:
__all__ = ["bar", "spam", "eggs"]
Run Code Online (Sandbox Code Playgroud)
另见http://docs.python.org/tutorial/modules.html
Len*_*bro 48
更新:今天您可能想要使用importlib
.
通过添加一个包来使Foo目录成为一个包__init__.py
.在那__init__.py
添加:
import bar
import eggs
import spam
Run Code Online (Sandbox Code Playgroud)
既然你想要它是动态的(这可能是也可能不是一个好主意),列出所有包含list dir的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
Run Code Online (Sandbox Code Playgroud)
然后,从您的代码执行以下操作:
import Foo
Run Code Online (Sandbox Code Playgroud)
您现在可以使用以下方式访问模块
Foo.bar
Foo.eggs
Foo.spam
Run Code Online (Sandbox Code Playgroud)
来自Foo import*的不是一个好主意,原因有几个,包括名称冲突和难以分析代码.
Luc*_*zzi 40
扩展Mihail的答案,我相信非hackish方式(如,不直接处理文件路径)如下:
__init__.py
在下创建一个空文件Foo/
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')
Run Code Online (Sandbox Code Playgroud)
你会得到:
<module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
<module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
Run Code Online (Sandbox Code Playgroud)
Eri*_*ski 24
对于那些无法让它工作的新手需要他们的双手.
创建一个文件夹/ home/el/foo并main.py
在/ home/el/foo下创建一个文件将此代码放在那里:
from hellokitty import *
spam.spamfunc()
ham.hamfunc()
Run Code Online (Sandbox Code Playgroud)制作一个目录 /home/el/foo/hellokitty
使文件__init__.py
下/home/el/foo/hellokitty
,并把这个代码有:
__all__ = ["spam", "ham"]
Run Code Online (Sandbox Code Playgroud)让两个Python文件:spam.py
和ham.py
下/home/el/foo/hellokitty
在spam.py中定义一个函数:
def spamfunc():
print "Spammity spam"
Run Code Online (Sandbox Code Playgroud)在ham.py中定义一个函数:
def hamfunc():
print "Upgrade from baloney"
Run Code Online (Sandbox Code Playgroud)运行:
el@apollo:/home/el/foo$ python main.py
spammity spam
Upgrade from baloney
Run Code Online (Sandbox Code Playgroud)Nia*_*las 16
我自己厌倦了这个问题,所以我写了一个名为automodinit的软件包来修复它.您可以从http://pypi.python.org/pypi/automodinit/获取.
用法是这样的:
automodinit
包包含在setup.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
Run Code Online (Sandbox Code Playgroud)
因此,"来自M import*"的效果恰好与"import M"匹配.
automodinit
很高兴从ZIP档案内部运行,因此ZIP安全.
尼尔
zmo*_*zmo 10
我知道我正在更新一个相当古老的帖子,我尝试使用automodinit
,但发现它的设置过程已经破解了python3.所以,根据Luca的回答,我提出了一个更简单的答案 - 这可能不适用于.zip - 这个问题,所以我想我应该在这里分享它:
在__init__.py
模块内yourpackage
:
#!/usr/bin/env python
import os, pkgutil
__all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)]))
Run Code Online (Sandbox Code Playgroud)
并在下面的另一个包中yourpackage
:
from yourpackage import *
Run Code Online (Sandbox Code Playgroud)
然后你将加载包中的所有模块,如果你编写一个新模块,它也将自动导入.当然,谨慎使用这种东西,拥有强大的力量是很重要的.
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
__import__(module)
Run Code Online (Sandbox Code Playgroud)
当from . 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
Run Code Online (Sandbox Code Playgroud)
请注意,这module_name not in globals()
是为了避免重新导入已经导入的模块,因为这可能会带来循环导入的风险。
小智 5
我也遇到过这个问题,这是我的解决方案:
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()
Run Code Online (Sandbox Code Playgroud)
此函数创建一个名为的文件(在提供的文件夹中)__init__.py
,该文件包含一个包含__all__
文件夹中每个模块的变量.
例如,我有一个名为的文件夹Test
,其中包含:
Foo.py
Bar.py
Run Code Online (Sandbox Code Playgroud)
所以在脚本中我想要导入模块我会写:
loadImports('Test/')
from Test import *
Run Code Online (Sandbox Code Playgroud)
这将从导入所有Test
和__init__.py
文件Test
将现在包含:
__all__ = ['Foo','Bar']
Run Code Online (Sandbox Code Playgroud)
Anurag Uniyal 回答并提出改进建议!
#!/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
Run Code Online (Sandbox Code Playgroud)
这是迄今为止我发现的最好的方法:
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())
Run Code Online (Sandbox Code Playgroud)
使用importlib
你唯一需要添加的是
from importlib import import_module
from pathlib import Path
__all__ = [
import_module(f".{f.stem}", __package__)
for f in Path(__file__).parent.glob("*.py")
if "__" not in f.stem
]
del import_module, Path
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
218310 次 |
最近记录: |