2010-08-06 17 views
5

Mam ten kod, który działa dobrze w Pythonie 2.5, ale nie w 2.7:python 2.7/exec/co jest nie tak?

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" 
""") 

I otrzymujemy:

 
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

drobne uwagi: pythonowy styl jest użycie TitleCase tylko dla klas, powinno być 'captureExec' lub' capture_exec'. Ponadto powinieneś szczególnie wychwycić 'ImportError' w bloku' try ... except '. – katrielalex

Odpowiedz

14

io.StringIO jest mylące w Pythonie 2.7, ponieważ jest przeniesiona z bajtów 3.x/string world. Ten kod robi ten sam błąd jak Twoja:

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

przyczyny:

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

Jeśli tylko przy użyciu Pythona 2.x, a następnie przejdź do modułu io całkowicie, i trzymać się StringIO. Jeśli naprawdę chcesz używać io zmienić swój import do:

from io import BytesIO as StringIO 
+0

+1 dla "BytesIO". Myślę, że wiele starych kodów 2.x nie będzie bardzo kompatybilnych z 2.7:/Wygląda na to, że 2.7 będzie bardziej odskocznią do 3.x –

2

To złe wieści

io.StringIO chce pracować z unicode. Można by pomyśleć, można naprawić poprzez umieszczenie u przed napisu, który chcesz wydrukować jak ten

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

jednak print jest naprawdę uszkodzony do tego, ponieważ powoduje 2 pisze do StringIO. Pierwszym z nich jest u"hello world" co jest w porządku, ale potem następuje z "\n"

więc zamiast trzeba napisać coś takiego

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