我有一些字符串形式的代码,想用它制作一个模块而不写入磁盘。
当我尝试使用 imp 和 StringIO 对象来执行此操作时,我得到:
>>> imp.load_source('my_module', '', StringIO('print "hello world"'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: load_source() argument 3 must be file, not instance
>>> imp.load_module('my_module', StringIO('print "hello world"'), '', ('', '', 0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: load_module arg#2 should be a file or None
如何在没有实际文件的情况下创建模块?或者,如何在不写入磁盘的情况下将 StringIO 包装在文件中?
更新:
注意:这个问题也是 python3 中的问题。
我尝试加载的代码仅部分受信任。我已经用 ast 检查了它并确定它不会导入任何东西或做任何我不喜欢的事情,但是当我有可能被修改的局部变量运行时,我对它的信任度不足以运行它,并且我不相信我自己的代码不会妨碍我尝试导入的代码。
我创建了一个只包含以下内容的空模块:
def load(code):
# Delete all local variables
globals()['code'] = code
del locals()['code']
# Run the code
exec(globals()['code'])
# Delete any global variables we've added
del globals()['load']
del globals()['code']
# Copy k so we can use it
if 'k' in locals():
globals()['k'] = locals()['k']
del locals()['k']
# Copy the rest of the variables
for k in locals().keys():
globals()[k] = locals()[k]
然后你可以导入 mymodule
并调用 mymodule.load(code)
。这对我有用,因为我确保我正在加载的代码不使用 globals
。此外, global
关键字只是一个解析器指令,不能引用 exec 之外的任何内容。
对于 import
没有写入磁盘的模块来说,这确实是太多的工作,但如果你想这样做,我相信这是最好的方法。
原文由 Conley Owens 发布,翻译遵循 CC BY-SA 4.0 许可协议
以下是将字符串作为模块导入的方法 ( Python 2.x ):
在 Python 3 中, exec 是一个函数,所以这应该有效:
现在访问模块属性(和函数、类等):
要忽略任何下一次导入尝试,请将模块添加到
sys
: