在运行时加载python代码

时间:2010-02-13 22:57:07

标签: python runtime python-import

我想在运行时加载.py文件。这个.py文件基本上是一个配置文件,格式如下:

var1=value  
var2=value  
predicate_function=func line : <return true or false>  

加载此文件后,我希望能够访问var1var2predicate_function。对于每一行,我将它传递给谓词函数,如果它返回false,我将忽略它。

在任何情况下,我都不确定如何在运行时加载python文件并访问其变量。

澄清:我可能需要将任意数量的配置文件传递给主程序,直到运行时我才会知道它们的名称。谷歌告诉我应该使用__import__。我不确定如何正确使用该方法,然后访问导入文件的变量。

9 个答案:

答案 0 :(得分:14)

python official documentation所述,如果您只是想按名称导入模块,可以在使用sys.modules后在__import__字典中查找。

假设您的配置位于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__语句的返回值,但必须完全理解how python works with namespaces and scopes

答案 1 :(得分:10)

您只需要能够动态指定导入,然后动态获取变量。

假设您的配置文件是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

然后你至少拥有所有的变量和功能。我从谓词函数中得不到你想要的东西,但也许你现在可以自己得到它。

答案 2 :(得分:7)

要访问其他Python模块,您导入。一些人已经提到过execfile,但它很混乱而且非常危险。 execfile使您的命名空间变得混乱,甚至可能弄乱您正在运行的代码。如果要访问其他Python源文件,请使用import语句。

更好的是根本不使用Python文件进行配置,而是使用内置模块ConfigParser或像JSON这样的序列化格式。这样,您的配置文件不允许执行任意(可能是恶意的)代码,不需要人们知道Python来配置您的程序,并且可以以编程方式轻松地进行更改。

答案 3 :(得分:7)

如果导入的模块位于常规搜索路径上,则可以使用__import__

如果您需要从文件系统中的任意路径加载模块,请使用imp.load_module

请务必考虑加载任意用户指定代码的安全隐患。

答案 4 :(得分:2)

在Python 2.*中,execfile有效(我建议传递一个特定字典并从那里访问变量 - 正如文档中的说明所说,execfile不能影响调用函数的locals()字典)。

在Python 3.*中,execfile已被删除,反之亦然:

with open('thefile.py') as f:
  exec(f.read(), somedict)

答案 5 :(得分:2)

我有点迟到了,但我想提出一个替代答案。

如果要在不影响全局模块名称空间的情况下导入代码,可以创建一个匿名模块(使用types.ModuleType)并在其中加载任意代码(使用compileexec) 。例如,像这样:

import types

filename = "/path/to/your/file.py"
with open(filename) as fp:
    code = compile(fp.read(), filename, "exec")
config_module = types.ModuleType("<config>")
exec code in config_module.__dict__

然后,您可以将变量视为config_module.var1,&amp; c。

答案 6 :(得分:1)

如果你想要一个只在程序没有运行时由用户编辑的配置文件,只需将它作为普通的python文件导入

main.py:

import config
print config.var1

config.py:

var="var12"
var2 = 100.5

答案 7 :(得分:0)

答案 8 :(得分:0)

由于Python版本尚未明确提及,因此值得指出的是, imp 模块在较新的Python版本中已被弃用,而不是importlib模块。 Example here.