【发布时间】:2017-01-02 04:14:18
【问题描述】:
我正在使用 python 2.7。我有一个文件夹,其中包含许多 .py 文件,这些文件定义了我想在我的主脚本中使用的函数、加载对象等。我想完成以下两个目标:
- 从该目录下的所有 .py 文件中加载所有对象,无需事先知道文件名。
- 在我的主脚本中访问这些对象而不使用前缀,例如无需使用
filename.function_name()
我了解这不符合公认的 Python 模块最佳实践。尽管如此:
我编写代码纯粹是为了我自己的使用。它永远不会与他人共享或被他人使用。
在我的开发工作过程中,我经常更改文件的名称,将对象定义从一个文件移动到另一个文件等。因此,需要进入我的主脚本并更改名称很麻烦每次我这样做时,函数名称前缀的数量。
我是成年人。我理解名称冲突风险的概念。我对我创建的函数和对象使用自己的命名约定,以确保它们不会与其他名称冲突。
我对此的第一次尝试是使用os.listdir() 遍历目录中的文件,然后在这些文件上调用execfile()。当这不起作用时,我在这里查看了回复:Loading all modules in a folder in Python。我发现了很多有用的东西,但没有一个能把我带到我想要的地方。具体来说,如果在我的__init__.py 文件中包含响应here:
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)]
然后在我的主脚本中使用:
os.chdir("/path/to/dir/") # folder that contains `Module_Dir`
from Module_Dir import *
然后我可以访问我目录中文件中定义的所有对象,而无需提前知道这些文件的名称(从而满足我的目标中的#1)。但是,这仍然需要我使用filename.function_name() 等调用这些函数和对象。同样,如果我明确地包含在我的__init__.py 文件中:
from filename1 import *
from filename2 import *
etc.
然后我可以在我的主脚本中使用与上面相同的from Module_Dir import *。现在,我可以在没有前缀的情况下访问我的对象,但它需要我明确指定 __init__.py 中的文件名。
是否有可以将这两者结合起来的解决方案,从而实现我的两个目标?我也试过(例如建议here,在__init__.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__ 的方式,或者使用python 2.7 的importlib 的应用程序,但在这两个方面都没有取得进展。
【问题讨论】:
-
一个 hacky 解决方案是在文件名更改时更新
__init__.py的辅助脚本。 -
@meetaig 这实际上不是一个坏主意——事实上,我可以在我的主脚本中使用一个非常小的、简单的函数来编写
__init__.py文件,然后将其导入。谢谢! -
没问题,很高兴能帮上忙!
-
无论如何请注意,
importlib也存在于 python2.7 中,即使功能很少。您可能想使用importlib.import_module而不是__import__,然后遍历该模块的所有属性并将它们分配给全局变量。 -
@Bakuriu 谢谢。究竟什么是最好的方法,特别是如果我不希望某些对象本身是全局变量(例如,为了将它们用作函数中的参数)?
标签: python python-2.7 module