2017-01-10 6 views
0

今私はPythonの関数の出力をキャッチし、変数に格納するためにこれを使用します。キャプチャおよび機能の表示コンソール出力

import io 
from contextlib import redirect_stdout 

def catch_output(func): 
    result = io.StringIO() 
    with redirect_stdout(result): 
     func() 
    return result.getvalue() 

output = catch_output(my_func) 

これは正常に動作しますが、それはまた、ミュートfunc呼び出しが終了するまでコンソールを起動します。 ライブの出力をコンソールに書き込んだりパイプしたりすることができますか?誰かが知っていますか?

+0

[スレッド](https://docs.python.org/3/library/threading.html)を試しましたか? – jshapy8

+0

Pythonの_teeストリームをグーグルで検索すると、合理的な解決策が得られるはずです。 –

+0

@justin_shapiroさんのコメントをさらに追加するには、同時に実行する必要がある少なくとも2つのことがあります。実行中の関数があり、ファイルバッファ(stdoutからリダイレクトされたもの)同時にそのバッファを定期的に何らかのストレージにコピーし、それを実際のstdoutに出力します。 – Aaron

答えて

1

あなたは前方に複数のファイルに書き込みカスタムファイルのようなオブジェクトに標準出力をリダイレクトすることができます

import contextlib 
import io 
import sys 


class TeeIO: 
    def __init__(self, original, target): 
     self.original = original 
     self.target = target 

    def write(self, b): 
     self.original.write(b) 
     self.target.write(b) 


@contextlib.contextmanager 
def tee_stdout(target): 
    tee = TeeIO(sys.stdout, target) 
    with contextlib.redirect_stdout(tee): 
     yield 


buf = io.StringIO() 
with tee_stdout(buf): 
    print("foo") 
print(buf.getvalue()) 
1

私が作ったコメントからの提案や、関数をスレッドに変換する例として、その関数の出力を定期的にチェックし、それを実際のstdoutにコピーすることができます。

import sys 
import time 
import threading 
from cStringIO import StringIO 

def foo(n): 
    for x in range(n): 
     time.sleep(1) #intense computation 
     print('test: {}'.format(n)) 


#i'm using python 2.7 so I don't have contextlib.redirect_stdout 
realstdout = sys.stdout 
sys.stdout = StringIO() 

t = threading.Thread(target=foo, args=(10,)) 
t.start() 

lastpos = 0 #last cursor position in file 

while True: 
    t.join(.1) #wait .1 sec for thread to complete 

    if sys.stdout.tell() != lastpos: #data has been written to stdout 
     sys.stdout.seek(lastpos) #go back to our last position 
     realstdout.write(sys.stdout.read()) #read the data to the real stdout 
     lastpos = sys.stdout.tell() #update lastpos 

    if not t.is_alive(): #when we're done 
     break 

sys.stdout.seek(0) #seek back to beginning of file 
output = sys.stdout.read() #copy to a usable variable 
sys.stdout = realstdout #reset stdout 
+0

node:私はpython 2.7を使用しているので、異なるセマンティクスがあるかもしれませんし、これを行うためのよりエレガントな方法です。ユニコードがどのように扱われるかの違いが最も顕著です – Aaron

+0

私はそれが2.7版を持っているのが良いと思います:) – Rotareti

0

これは私が使用して終了するものです。私は、私のように、授業や勉強に苦労している人のためにここに残したと思った。

import sys 
import io 
from contextlib import redirect_stdout 


def get_multi_writer(streams): 
    writer = type('obj', (object,), {}) 
    writer.write = lambda s: [stream.write(s) for stream in streams] 
    return writer 


def catch_output(func, args, kwargs): 
    streams = [sys.stdout, io.StringIO()] 
    with redirect_stdout(get_multi_writer(streams)): 
     func(*args, **kwargs) 
    return streams[1].getvalue() 


print(catch_output(my_func, [], {})) 
関連する問題