绊倒this question后,我一直在玩exec()以更好地了解它是如何工作的。我试图让脚本憎恶增加一个全局变量,读取它自己,并用新的全局值调用exec,直到满足递归限制。我能想到的最好的方法是让一个文件声明全局,然后调用下一个文件(一个完全重复的减去变量声明),然后递归调用自己。这是第一个代码:
# recurse.py
def func():
global x
x += 1
with open('recurse2.py', 'r') as f:
try:
exec(f.read(), {'x': x})
except RecursionError:
print('maximum recursion depth reached at', x)
x = 0
func()
这是它执行的文件,它将自行执行:
# recurse2.py
def func():
global x
x += 1
with open('recurse2.py', 'r') as f:
try:
exec(f.read(), {'x': x})
except RecursionError:
print('maximum recursion depth reached at', x)
func()
仅使用一个文件是否可以达到相同的效果?
答案 0 :(得分:2)
你可以这样做:
# recurse.py
def func():
global x
x += 1
with open('recurse.py', 'r') as f:
try:
exec(f.read(), {'x': x})
except RuntimeError:
print('maximum recursion depth reached at', x)
try:
x
except NameError:
x = 0
func()
您的初始示例的问题并非真正针对exec
。只是程序本身在调用x
之前将func
设置为零。因此,传入x
的起始值无效:您执行的代码无论如何都会设置x
的新值。在这个新版本中,try / except块在将名称初始化为零之前测试名称是否已存在。
(我在这里使用了RuntimeError,因为我没有引入RecursionError的Python 3.5,但它应该与RecursionError一样。)
答案 1 :(得分:2)
由于太多文件被打开,@ BrenBarn的优秀解决方案因RuntimeError(@ ~500递归)而不是IOError(@ ~256递归)而失败:
#recurse.py
def func():
global x
x += 1
with open('recurse.py') as source:
string = source.read()
try:
exec(string, {'x': x})
except RuntimeError:
print('maximum recursion depth reached at', x)
try:
x
except NameError:
x = 0
func()
但是,您也可以根据需要扩展递归堆栈(sys.setrecursionlimit()
)和/或打开文件限制(ulimit -n
)。