我正在尝试创建一个模块并从字符串中运行它,但我得到一个例外:
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
,换句话说,它不会访问此范围内的其他变量。谢谢。
答案 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