如何从字符串中的代码加载模块? [英] How to load a module from code in a string?

查看:31
本文介绍了如何从字符串中的代码加载模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些字符串形式的代码,想用它制作一个模块而不写入磁盘.

I have some code in the form of a string and would like to make a module out of it without writing to disk.

当我尝试使用 imp 和 StringIO 对象来执行此操作时,我得到:

When I try using imp and a StringIO object to do this, I get:

>>> 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 包装在文件中?

How can I create the module without having an actual file? Alternatively, how can I wrap a StringIO in a file without writing to disk?

更新:

注意:这个问题也是python3的问题.

NOTE: This issue is also a problem in python3.

我尝试加载的代码只是部分可信.我已经用 ast 完成了它并确定它不会导入任何东西或做任何我不喜欢的事情,但是当我有可能被修改的局部变量运行时,我不相信它足以运行它,并且我不相信我自己的代码会妨碍我尝试导入的代码.

The code I'm trying to load is only partially trusted. I've gone through it with ast and determined that it doesn't import anything or do anything I don't like, but I don't trust it enough to run it when I have local variables running around that could get modified, and I don't trust my own code to stay out of the way of the code I'm trying to import.

我创建了一个只包含以下内容的空模块:

I created an empty module that only contains the following:

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 之外的任何内容.

Then you can import mymodule and call mymodule.load(code). This works for me because I've ensured that the code I'm loading does not use globals. Also, the global keyword is only a parser directive and can't refer to anything outside of the exec.

在不写入磁盘的情况下import模块确实需要太多的工作,但是如果您想这样做,我相信这是最好的方法.

This really is way too much work to import the module without writing to disk, but if you ever want to do this, I believe it's the best way.

推荐答案

这里是如何将字符串作为模块导入(Python 2.x):

Here is how to import a string as a module (Python 2.x):

import sys,imp

my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec my_code in mymodule.__dict__

Python 3 中,exec 是一个函数,所以这应该可以工作:

In Python 3, exec is a function, so this should work:

import sys,imp

my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec(my_code, mymodule.__dict__)

现在访问模块属性(和函数、类等):

Now access the module attributes (and functions, classes etc) as:

print(mymodule.a)
>>> 5

要忽略任何下一次导入尝试,请将模块添加到 sys:

To ignore any next attempt to import, add the module to sys:

sys.modules['mymodule'] = mymodule

这篇关于如何从字符串中的代码加载模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆