2010-08-06 85 views
5

我有這樣的代碼,其運行正常在Python 2.5,但不是在2.7:python 2.7/exec /出了什麼問題?

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

小意見:Python的風格是隻使用首字母大寫的類,它應該是'captureExec'或'capture_exec'。另外,你應該特別抓住'try ... except'塊中的'ImportError'。 – katrielalex 2010-08-06 12:39:20

回答

14

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 
+0

「BytesIO」的+1。我認爲很多舊的2.x代碼不會與2.7兼容:/看起來像2.7將會更像是3.x的墊腳石 – 2010-08-06 13:12:25

2

這是個壞消息

io.StringIO希望與Unicode的工作。你可能會認爲你可以通過把一個u中要打印這樣

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

然而print確實打破了這個,因爲它會導致2寫入到StringIO的字符串前解決它。第一個是u"hello world"這是很好的,但隨後與"\n"

如下所以不是你需要寫這樣的事情

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