簡體   English   中英

python:在 exec 語句中獲取打印 output

[英]python: get the print output in an exec statement

我想得到一個exec(...)的 output 這是我的代碼:

code = """
i = [0,1,2]
for j in i :
    print j
"""
result = exec(code)

我怎樣才能得到打印輸出的東西? 我怎樣才能得到類似的東西:

0
1
2

問候和感謝。

由於 Python 3.4 有一個解決方案是 stdlib: https ://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout

from io import StringIO
from contextlib import redirect_stdout

f = StringIO()
with redirect_stdout(f):
    help(pow)
s = f.getvalue()

在舊版本中,您可以編寫上下文管理器來處理替換標准輸出:

import sys
from io import StringIO
import contextlib

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

code = """
i = [0,1,2]
for j in i :
    print j
"""
with stdoutIO() as s:
    exec(code)

print("out:", s.getvalue())

您可以在 exec 調用期間將標准輸出重定向到字符串:

Python2

import sys
from cStringIO import StringIO

code = """
i = [0,1,2]
for j in i:
    print(j)
"""

old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec(code)
sys.stdout = old_stdout

print(redirected_output.getvalue())

Python3

import sys
from io import StringIO

code = """
i = [0,1,2]
for j in i:
    print(j)
"""

old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec(code)
sys.stdout = old_stdout

print(redirected_output.getvalue())

這是@Jochen 答案的 Py3 友好版本。 我還添加了try-except子句以在code出錯的情況下進行恢復。

import sys
from io import StringIO
import contextlib

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

code = """
i = [0,1,2]
for j in i :
    print(j)
"""
with stdoutIO() as s:
    try:
        exec(code)
    except:
        print("Something wrong with the code")
print("out:", s.getvalue())

這是對弗雷德里克答案的一個小修正。 我們需要在exec()中處理可能的異常以返回正常的stdout 否則我們看不到更遠的print輸出:

code = """
i = [0,1,2]
for j in i :
print j
"""

from cStringIO import StringIO
old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
try:
    exec(code)
except:
    raise 
finally: # !
    sys.stdout = old_stdout # !

print redirected_output.getvalue()
...
print 'Hello, World!' # now we see it in case of the exception above

Python 3:將 exec 的輸出放入變量中

import io, sys
print(sys.version)

#keep a named handle on the prior stdout 
old_stdout = sys.stdout 
#keep a named handle on io.StringIO() buffer 
new_stdout = io.StringIO() 
#Redirect python stdout into the builtin io.StringIO() buffer 
sys.stdout = new_stdout 

#variable contains python code referencing external memory
mycode = """print( local_variable + 5 )""" 

local_variable = 2
exec(mycode)

#stdout from mycode is read into a variable
result = sys.stdout.getvalue().strip()

#put stdout back to normal 
sys.stdout = old_stdout 
 
print("result of mycode is: '" + str(result) + "'") 

印刷:

3.4.8
result of mycode is: '7'

還提醒您,python exec(...)是邪惡的和壞的,因為 1. 它使您的代碼變成不可讀的 goto-spaghetti。 2. 引入最終用戶代碼注入機會,以及 3. 將異常堆棧跟蹤拋入混亂,因為 exec 是由線程組成的,並且線程是壞的 mmkay。

就像是:

 codeproc = subprocess.Popen(code, stdout=subprocess.PIPE)
 print(codeproc.stdout.read())

應該在不同的進程中執行代碼,並通過codeproc.stdout將輸出傳回主程序。 但我沒有親自使用它,所以如果我做錯了什么,請隨時指出:P

您可以將 exec 與 eval 結合使用以獲取列表輸出:

ExecString('i = [0,1,2]');
println(EvalStr('[j for j in i]'));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM