python 2.7 / exec / 出了什么问题?

5 投票
2 回答
5528 浏览
提问于 2025-04-16 02:25

我有一段代码,在Python 2.5中运行得很好,但在2.7中就不行了:

import sys
import traceback
try:
    from io import StringIO
except:
    from StringIO import StringIO

def CaptureExec(stmt):
    oldio = (sys.stdin, sys.stdout, sys.stderr)
    sio = StringIO()
    sys.stdout = sys.stderr = sio
    try:
        exec(stmt, globals(), globals())
        out = sio.getvalue()
    except Exception, e:
        out = str(e) + "\n" + traceback.format_exc()
    sys.stdin, sys.stdout, sys.stderr = oldio
    return out

print "%s" % CaptureExec("""
import random
print "hello world"
""")

然后我得到了:

string argument expected, got 'str'
Traceback (most recent call last):
  File "D:\3.py", line 13, in CaptureExec
    exec(stmt, globals(), globals())
  File "", line 3, in 
TypeError: string argument expected, got 'str'

2 个回答

2

这可不是个好消息

io.StringIO 是想处理 Unicode 字符串的。你可能会想,通过在你想打印的字符串前加一个 u 来解决这个问题,比如这样:

print "%s" % CaptureExec("""
import random
print u"hello world"
""")

但是 print 在这里其实是有问题的,因为它会导致向 StringIO 写入两次。第一次是 u"hello world",这没问题,但接下来又写了 "\n"

所以你需要这样写:

print "%s" % CaptureExec("""
import random
sys.stdout.write(u"hello world\n")
""")
15

io.StringIO 在 Python 2.7 中让人感到困惑,因为它是从 3.x 版本的字节/字符串世界移植过来的。这段代码会出现和你一样的错误:

from io import StringIO
sio = StringIO()
sio.write("Hello\n")

原因:

Traceback (most recent call last):
  File "so2.py", line 3, in <module>
    sio.write("Hello\n")
TypeError: string argument expected, got 'str'

如果你只在使用 Python 2.x,那就完全可以不使用 io 模块,直接使用 StringIO。如果你真的想用 io,可以把你的导入改成:

from io import BytesIO as StringIO

撰写回答