exec() 遇到 : 字符时引发 '意外的 EOF' 错误

2 投票
2 回答
2032 浏览
提问于 2025-04-16 16:20

在我写的这个程序(一个基于文本的角色扮演游戏)中,我打算加入“脚本”,也就是一些小代码块,可以让游戏更有互动性(比如当你进入一个房间时,有个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 个回答

4

你可以用 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

下面的代码在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文本框这样的工具会好得多。

撰写回答