2016-09-19 6 views
4

私はいくつかのライブラリを使用しています(残念なことに、私の不気味さ)は、特定のデバッグ情報をstdoutに出力します。私は最近、もちろん標準出力を必要とし、端末にユーザの入力や印刷出力を取得するためのコードを追加したpythonでstdoutを強制終了するget_line_buffer()

import sys,os 
sys.stdout = open(os.devnull,'wb') 

:さて、何の問題、私はただでそれを無効にしません。しかし、再び、全く問題は、代わりにprintの私はちょうど行うことができます。

sys.__stdout__.write('text\n') 

を最後に、私は別のスレッドやユーザーのタイピングを中断することができ、プログラムの出力にraw_inputをやっているので、私は再びエコーしたかったですreadline.get_line_buffer()を使用して多かれ少なかれシームレスにするためにin the first part of this answerと記載されているようにテストしてください。

> foobar 
し、別のスレッドが Interrupting text!が、それはのようになります。こう述べています。たとえば、ユーザーが foobarを入力した場合

Interrupting text! 
> foobar 

しかし、その代わりに、私は観察:

Interrupting text! 
> 

それはことが判明しますreadline.get_line_buffer()は常に空白で、コードはユーザーが入力した内容を再エコーしません。 sys.stdoutのオーバーライドを削除すると、すべてが正常に動作します(ただし、ライブラリのデバッグ出力はブロックされません)。

LinuxでPython 2.7を使用しています。私がやりたいことはおそらく不可能ですが、なぜこれが起こっているのか本当に知りたいです。私の考えでは、stdoutでの作業は、stdinラインバッファには影響を及ぼしませんが、根底にあるライブラリや実装については熟知していません。

以下に、最小の使用例を示します。ちょうど何かを入力して、中断するテキストを待ちます。プロンプト"> "は再エコーされますが、入力したテキストは表示されません。 2行目をコメントアウトして正しく動作することを確認してください。スレッドが印刷されると、ラインバッファーはstdin.logに記録されます。

import time,readline,thread,sys,os 
sys.stdout = open(os.devnull,'wb') # comment this line! 

def noisy_thread(): 
    while True: 
    time.sleep(5) 
    line = readline.get_line_buffer() 
    with open('stdin.log','a') as f: 
     f.write(time.asctime()+' | "'+line+'"\n') 
    sys.__stdout__.write('\r'+' '*(len(line)+2)+'\r') 
    sys.__stdout__.write('Interrupting text!\n') 
    sys.__stdout__.write('> ' + line) 
    sys.__stdout__.flush() 

thread.start_new_thread(noisy_thread,()) 
while True: 
    sys.__stdout__.write('> ') 
    s = raw_input() 

私もget_line_buffer()呼び出しの前sys.stdout = sys.__stdout__権利を試してみたが、それはどちらか動作しません。どんな助けや説明も大歓迎です。

+0

ライブラリコードからstdout *または* stderrへの印刷がばかげているので、代わりに 'logging'を使うようにプルリクエストを送信したいと思います。あるいは、少なくともバグレポートを提出してください。そして、おそらく名前と恥があるかもしれません:P –

+0

私はちょうどクイックラッパークラスを書きました。そして、 'stdout'に取って代わる何かがreadlineの振る舞いを破るように見えます。 –

+0

ありがとう、私はそれをしましたが、それまでの間、私はまだ本当にこれが起こっていることを知りたいです:) – TheSchwa

答えて

1

raw_input()は、stdoutをリダイレクトするときに機能しなくなります。 raw_input()の直前にsys.stdout = sys.__stdout__を入力すると、再び機能します。 raw_inputを動作させるには、stdinstdoutの両方を端末に接続する必要があります。

+0

あなたはそれがとても意味をなさないと言いました。ちょうど私自身のためにそれを動かすことができなかった。ありがとう! – TheSchwa

関連する問題