Python 2.7 / exec / ce qui est faux?
Question
J'ai ce code qui fonctionne très bien en Python 2.5, mais pas dans 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"
""")
Et je reçois:
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'
La solution
io.StringIO
est source de confusion dans Python 2.7, car il est backported de les octets 3.x / world string. Ce code obtient la même erreur que le vôtre:
from io import StringIO
sio = StringIO()
sio.write("Hello\n")
causes:
Traceback (most recent call last):
File "so2.py", line 3, in <module>
sio.write("Hello\n")
TypeError: string argument expected, got 'str'
Si vous utilisez uniquement Python 2.x, puis passez le module io
tout à fait, et le bâton avec StringIO. Si vous voulez vraiment utiliser io
, changer votre importation:
from io import BytesIO as StringIO
Autres conseils
Il est de mauvaises nouvelles
io.StringIO veut travailler avec unicode. Vous pourriez penser que vous pouvez y remédier en mettant un u
devant la chaîne que vous souhaitez imprimer comme ceci
print "%s" % CaptureExec("""
import random
print u"hello world"
""")
Cependant print
est vraiment rompu pour cela car il provoque 2 écritures au StringIO. Le premier est u"hello world"
ce qui est bien, mais il suit avec "\n"
au lieu vous devez écrire quelque chose comme ceci
print "%s" % CaptureExec("""
import random
sys.stdout.write(u"hello world\n")
""")