exec() 遇到 : 字符时引发 '意外的 EOF' 错误
在我写的这个程序(一个基于文本的角色扮演游戏)中,我打算加入“脚本”,也就是一些小代码块,可以让游戏更有互动性(比如当你进入一个房间时,有个NPC跟你打招呼)。自己写一个脚本语言或解析器感觉任务太大了,所以我想直接用Python代码来实现。Python可以满足我对脚本的所有需求,所以我开始动手了。对于简单的事情,比如打印信息或者数学运算,exec()运行得很好。但是当我遇到一个代码块时,就出现了问题。下面是它的运行情况:
首先 - 正常工作的代码(来自交互式命令行):
>>> x = ''
>>> y = []
>>> while x != '@':
y.append(x)
x = raw_input(compile('''''', '<string>', 'exec'))
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>name = 'Drew'
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>print 'Hello, %s' % name
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>@
>>> del x[0] # removes the empty field created by the first y.append(x)
>>> for line in y:
exec line
>>> Hello, Drew
现在是错误信息(同样来自交互式命令行):
>>> x = ''
>>> y = []
>>> while x != '@':
y.append(x)
x = raw_input(compile('''''', '<string>', 'exec'))
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>name = 'Drew'
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>if name == 'Drew':
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>print 'Hi, %s!' % name
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>else:
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>print 'Greetings, stranger.'
<code object <module> at 0000000002B1DBB0, file "<string>", line 1>@
>>> del y[0]
>>> for line in y:
exec line
Traceback (most recent call last):
File "<pyshell#308>", line 2, in <module>
exec line
File "<string>", line 1
if name == 'Drew':
^
SyntaxError: unexpected EOF while parsing
所以你可以看到,: 这个字符(在选择代码块时是必须的)导致exec出错。我有什么办法可以解决这个问题吗?我尝试了好几个小时,但就是找不到解决办法。难道这根本不可能吗?
非常感谢你阅读这个内容,我很感激你给我的所有帮助。
2 个回答
你可以用 exec
来执行一行代码。在这段代码中:
if a == b:
do_c()
第一行单独执行时,会出现语法错误。上面的代码也可以简化成一行,像这样:
if a == b: do_c()
在更一般的情况下,如果允许多行代码,你可以把所有的输入内容收集到一个字符串里(记得保持正确的空格),然后再用 exec
来执行这个字符串:
source = '''
name = "joe"
if name == "joe":
print "hi joe"
else:
print "hi stranger"
'''
exec source
你已经知道要用一个特殊字符(@
)来结束输入,但你还需要确保用户在写多行语句时,能够提供正确的空格格式,这样Python才能正确理解。
下面的代码在2.7版本中从IDLE编辑窗口运行时可以正常工作:
line=''
lines = []
print "Enter Python lines (@ to quit):"
while line != '@':
line=raw_input()
lines.append(line)
lines.pop() # delete '@' line
lines = '\n'.join(lines)
exec lines
在Shell窗口中的结果是:
>>>
Enter Python lines (@ to quit):
name = 'Terry'
if name == 'Drew':
print 'Hi Drew'
else:
print 'Hi stranger'
@
Hi stranger
需要注意的是,代码行之间要用'\n'连接,而不是用空字符串''。另外,连接后,代码片段的末尾不要加'\n'。我觉得这可能是早期版本的Python的问题,因为在多行代码块中,exec可能需要一个结束的'\n'。
不过,这种输入代码的方式真是糟糕。我尝试了三次才没有出错地输入上面的代码!对于初次输入和编辑来说,使用像tkinter文本框这样的工具会好得多。