给出以下示例布局:
test/
test.py
formats/
__init__.py
format_a.py
format_b.py
我尝试归档的是,每当import formats
,__init__.py
查找formats
子目录中的所有可用模块时,加载它们并使它们可用(现在只需通过变量supported_formats
)。如果有一个更好,更pythonic或以其他方式动态加载运行时的东西,基于物理可用文件,请告诉。
我试过这样的事情(在__init__.py
中):
supported_formats = [__import__(f[:f.index('.py')]) for f in glob.glob('*.py')]
到目前为止,当我从命令行(来自formats子目录或其他目录)运行__init__.py
时,我才开始工作。但是当我从test.py
导入它时,它会像我这样对我发誓:
ImportError: No module named format_a.py
当我从python解释器导入它时,当我在另一个目录中启动解释器但formats
子目录时。
这是整个代码。它还查找一个特定的类并在dict中存储每个类的一个实例,但动态加载模块是我不能得到的主要部分:
def dload(get_cls=True, get_mod=True, key=None, fstring_mod='*.py', fstring_class=''):
if p.dirname(__file__):
path = p.split(p.abspath(__file__))[0]
fstring_mod = p.join(path, fstring_mod)
print >> sys.stderr, 'Path-Glob:', fstring_mod
modules = [p.split(fn)[1][:fn.index('.py')] for fn in glob.glob(fstring_mod)]
print >> sys.stderr, 'Modules:', ', '.join(modules)
modules = [__import__(m) for m in modules]
if get_cls:
classes = {} if key else []
for m in modules:
print >> sys.stderr, "-", m
for c in [m.__dict__[c]() for c in m.__dict__ if c.startswith(fstring_class)]:
print >> sys.stderr, " ", c
if key:
classes[getattr(c, key)] = c
else:
classes.append(c)
if get_mod:
return (modules, classes)
else:
return classes
elif get_mod:
return modules
_supported_formats = dload(get_mod=False, key='fid', fstring_mod='format_*.py', fstring_class='Format')
无论如何,整个文件系统路径等的混乱可能都是混乱的。我想用模块名称空间或类似的东西来处理这个问题,但我现在有点失去了如何开始以及如何处理模块,因此它们可以从任何地方访问。
答案 0 :(得分:1)
您需要对代码进行两处修复:
您应该拨打__import__(m, globals(), locals())
而不是__import__(m)
。这需要Python在包中找到模块。
由于您在错误的字符串上调用index(),因此您的代码无法正确删除.py扩展名。如果它始终是.py扩展名,则只需使用p.split(fn)[1][:-3]
代替。
答案 1 :(得分:1)
首先,您必须使其无论当前工作目录如何,您的代码都能正常工作。为此,您使用__file__
变量。您还应该使用绝对导入。
所以像(未经测试):
supported_formats = {}
for fn in os.listdir(os.path.dirname(__file__)):
if fn.endswith('.py'):
exec ("from formats import %s" % fn[:-3]) in supported_formats
答案 2 :(得分:0)
在sys.path中搜索模块。您应该能够使用模块的路径扩展sys.path。我也不确定你是否可以使用'module.py'约定在sys.path上加载模块,我认为不首选'.py'。
这显然不是一个解决方案,但可能会很方便。
答案 3 :(得分:0)
我想如果你做了一些事情,'格式'将是你的包,所以当你告诉它import formats
你应该能够访问该包内的其余模块,所以,你会有一些东西比如formats.format_a.your_method
不确定,我只是一个n00b。
答案 4 :(得分:0)
这是我在interjay修正后提出的代码。仍然不确定这是不是很好的风格。
def load_modules(filemask='*.py', ignore_list=('__init__.py', )):
modules = {}
dirname = os.path.dirname(__file__)
if dirname:
filemask = os.path.join(dirname, filemask)
for fn in glob.glob(filemask):
fn = os.path.split(fn)[1]
if fn in ignore_list:
continue
fn = os.path.splitext(fn)[0]
modules[fn] = __import__(fn, globals(), locals())
return modules