非同期出力をうまく処理するpython REPLを実装する方法は?
-
22-07-2019 - |
質問
簡単な読み取り-評価-印刷-ループでいくつかのコマンドを受け入れることができるPythonベースのアプリがあります。 raw_input( '>')
を使用して入力を取得しています。 Unixベースのシステムでは、 readline
をインポートして、動作を少し改善します。これはすべて正常に動作しています。
問題は、入ってくる非同期イベントがあるということであり、出力が発生したらすぐに出力したいのです。残念ながら、これにより物事が見苦しくなります。 "> "文字列は出力後に再び表示されず、ユーザーが何かを入力している途中である場合、テキストを半分に切り詰めます。何かを印刷した後、おそらくユーザーの進行中のテキストを再描画する必要があります。
これは、解決された問題に違いないようです。これを行う適切な方法は何ですか?
一部のユーザーはWindowsベースです。
TIA
編集:受け入れられた答えはUnixyプラットフォームで動作します(readlineモジュールが利用可能な場合)が、Windowsでこの動作を行う方法を知っている人がいれば、大歓迎です!
解決
たぶん、このような何かがトリックを行うでしょう:
#!/usr/bin/env python2.6
from __future__ import print_function
import readline
import threading
PROMPT = '> '
def interrupt():
print() # Don't want to end up on the same line the user is typing on.
print('Interrupting cow -- moo!')
print(PROMPT, readline.get_line_buffer(), sep='', end='')
def cli():
while True:
cli = str(raw_input(PROMPT))
if __name__ == '__main__':
threading.Thread(target=cli).start()
threading.Timer(2, interrupt).start()
stdinはスレッドセーフではないと思うので、割り込みスレッドで文字が失われる可能性があります( interrupt
の最後にユーザーが再入力する必要があります)。 time.sleep
呼び出しで interrupt
の時間を誇張しました。 readline.get_line_buffer
の呼び出しでは、失われた文字は表示されないため、すべて大丈夫です。
stdout自体はスレッドセーフではないことに注意してください。そのため、複数の実行スレッドが中断している場合でも、これは結果的に大雑把に見えます。
他のヒント
raw_input()
を使用して独自のREPLを記述する理由 cmd.Cmd
クラスを見ましたか? 編集: sclapp ライブラリを見つけました。便利になります。
注: cmd.Cmd
クラス(およびsclapp)は、元の目標を直接サポートする場合としない場合があります。その機能を提供するために、サブクラス化し、必要に応じて変更する必要がある場合があります。
これを実行:
python -m twisted.conch.stdio
スレッドを使用せずに、素敵な色付きの非同期REPLを取得します。プロンプトを入力している間、イベントループが実行されています。
コードモジュールを調べると、Pythonコードを解釈するためのオブジェクトも作成できます(恥知らずのプラグ) https:// github.com/iridium172/PyTerm を使用すると、生のキーボード入力を処理するインタラクティブなコマンドラインプログラムを作成できます(^ CはKeyboardInterruptを発生させます)。
これは一種の無回答ですが、 IPython のコードを見て、彼らがそれをどのように行っているかを見てください。
2つの基本的なオプションがあると思います:
- 出力を同期します(つまり、戻るまでブロックします)
- 入力と(非同期)出力を、おそらく2つの別々の列に分けます。