Python从字符串创建一个模块并运行该模块

时间:2018-06-12 05:13:26

标签: python python-3.x

我正在尝试创建一个模块并从字符串中运行它,但我得到一个例外:

File "<frozen importlib._bootstrap>", line 568, in module_from_spec
AttributeError: 'str' object has no attribute 'loader'

我的尝试:

from importlib.util import module_from_spec

task_string = """
print ('Hello world!')        
        """
module = module_from_spec("module_name")
exec(task_string, module.__dict__)

我知道我可以使用eval(task_string)但我想在沙箱中运行task_string,换句话说,它不会访问此范围内的其他变量。谢谢。

1 个答案:

答案 0 :(得分:1)

回复:评论中的讨论:

考虑这个例子:

var = "123"

code = "print(var)"

exec(code)

像这样调用exec将执行当前范围内的字符串,因此它可以访问您的var并打印&#34; 123&#34;。

但您可以通过指定应分别用作全局和本地的字典来限制eval的上下文:

var = "123"

code = "print(var)"

sandbox_globals = {}    
sandbox_locals = {}

exec(code, sandbox_globals, sandbox_locals)

这里会引发一个例外:

NameError: name 'var' is not defined

因为您已指定要使用的全局变量和本地变量。

您可以通过以下内容明确允许exec访问:

sandbox_globals = {'var':var}

但是,您还没有完全以这种方式限制沙箱。

sandbox_locals = {}
sandbox_globals = {}

code = "print(2**8)"

exec(code, sandbox_globals, sandbox_locals)

此代码无需抛出即可工作,打印256. print有效,并且来自某个地方。这是因为__builtins__会自动添加到sandbox_globals,如果您没有明确阻止:{/ p>

sandbox_locals = {}
sandbox_globals = {}

code = "print(2**8)"

sandbox_globals['__builtins__'] = {}

exec(code, sandbox_globals, sandbox_locals)

这会引发异常,因为您不再提供print

NameError: name 'print' is not defined