我想从用户那里执行一个程序。它应该能够从我允许的主程序中调用函数,并且可以在主程序中更改变量,但是如果没有这些允许的函数,它就不能在主程序中更改变量。
主程序:
import traceback
def forward():
if pos < 100:
pos += 1
return True
else:
return False
def private():
print "I'm private!"
pos = 0
print(pos)
path = input("Enter the path to your program: ")
try:
program = open(path)
code = compile(program.read(), path, "exec")
# exec code in a way that allows the code to use the forward function
except:
traceback.print_exc()
finally:
program.close()
print(pos)
输入包含内容
的文件的路径if forward():
print("walked forward")
else:
print("couldn't walk forward")
应该给出输出
0
walked forward
1
输入包含内容
的文件的路径pos = 10 # should be a local variable for the users program
应该给出输出
0
0
输入包含内容
的文件的路径private()
应该给出例外
NameError: name 'private' is not defined
输入包含内容
的文件的路径pos += 5
应该给出例外
NameError: name 'pos' is not defined
答案 0 :(得分:1)
作为exec函数的一部分,您可以传递一个字典,该字典将用作命名空间来执行代码。这可以防止意外滥用私有函数和变量。但是,这绝不是安全的。确定的人仍然可以访问private
和pos
。
exec(code, {"forward": forward})
要证明函数引用的全局变量始终是它所定义的模块的全局变量。
value = 0
def getter():
return value
def setter(new_value):
global value
value = new_value
source = """
assert getter() == 0, "expected 0, but got {}".format(getter())
setter(1)
value = -1
assert getter() == 1, "expected 1, but got {}".format(getter())
"""
try:
exec(source) # using this modules globals
except AssertionError as e:
print("executed source, but it raised an AssertionError")
print(e)
else:
assert value == -1
print("executed source, but it modified our value")
value = 0 # reset value
exec(source, {"getter": getter, "setter": setter}) # no assertion error
assert value == 0
print("executed source, and it did not modify our value")