运行时加载Python代码
我想在程序运行时加载一个 .py
文件。这个 .py
文件其实是一个配置文件,格式如下:
var1=value
var2=value
predicate_function=func line : <return true or false>
加载这个文件后,我希望能够访问里面的 var1
、var2
和 predicate_function
。对于每一行数据,我会把它传给这个判断函数,如果返回的是假(false),我就会忽略这一行。
不过,我不太确定怎么在运行时加载一个 Python 文件并访问它的变量。
补充说明:我可能需要传入多个这样的配置文件到主程序中,而我在运行之前并不知道这些文件的名字。谷歌告诉我应该使用 __import__
,但我不太清楚怎么正确使用这个方法来访问导入文件里的变量。
9 个回答
要使用另一个Python模块,你需要导入它。有些人提到过execfile
,但这方法比较麻烦而且有风险。使用execfile
会让你的命名空间变得混乱,甚至可能会影响你正在运行的代码。当你想要访问另一个Python源文件时,最好使用import
语句。
更好的做法是根本不使用Python文件来配置,而是使用内置的ConfigParser
模块或者像JSON这样的序列化格式。这样一来,你的配置文件就不会执行任意(可能是恶意的)代码,也不需要人们懂Python就能配置你的程序,而且可以很方便地通过程序进行修改。
根据Python官方文档的说明,如果你只是想通过名字导入一个模块,可以在使用__import__
之后,在sys.modules
字典中查找它。
假设你的配置在myproject.mymodule
中,你可以这样做:
module_name = 'myproject.mymodule'
import sys
__import__(module_name)
mymodule = sys.modules[module_name]
# Then you can just access your variables and functions
print mymodule.var1
print mymodule.var2
# etc...
你也可以使用__import__
语句的返回值,但你需要完全理解Python是如何处理命名空间和作用域的。
你只需要能够动态地指定要导入的内容,然后动态地获取这些变量。
假设你的配置文件是 bar.py,内容如下:
x = 3
y = 4
def f(x): return (x<4)
那么你的代码应该像这样:
import sys
# somehow modnames should be a list of strings that are the names of config files
#
# you can do this more dynamically depending on what you're doing
modnames = ['bar']
for modname in modnames:
exec('import %s' % modname)
for modname in modnames:
mod = sys.modules[modname]
for k in mod.__dict__:
if k[:2] != '__':
print modname, k, mod.__dict__[k]
我得到了这个输出:
bar f <function f at 0x7f2354eb4cf8>
bar x 3
bar y 4
这样你至少可以获取到所有的变量和函数。我不太明白你想从谓词函数中得到什么,但也许你现在可以自己搞定了。