2

背景: readlineライブラリを使用して入力を処理するシェルのようなアプリケーションに接続するPythonサブプロセスがあり、そのアプリには、bashと同様にコマンド入力用のTABコンプリートルーチンがあります。次のように、子プロセスが生成されます。

def get_cli_subprocess_handle():
    return subprocess.Popen(
                            '/bin/myshell',
                            shell=False,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            )

タブコンプリートを除いて、すべてがうまく機能します。Pythonプログラムがタブ文字'\t'をサブプロセスに渡すときはいつでも、readlineライブラリのタブ完了ルーチンをトリガーする代わりに、STDINに5つのスペースを取得します。:(

質問: 子のタブ完了機能をトリガーするために、サブプロセスのSTDINに何を送信できますか?別の方法で質問されるかもしれません。可能であれば、TAB文字ではなくTABキーを送信するにはどうすればよいですか。

関連しているが未回答で脱線している:

readlineを中心に構築されたPythonバッチプロセスのトリガータブ補完

4

3 に答える 3

3

シェルのようなアプリケーションは、おそらく標準入力に接続されている端末とそれに接続されているパイプを区別しています。多くの Unix ユーティリティは、バッファリング (行とブロック) を最適化するためにそれを行います。シェルのようなユーティリティは、予期しない結果を避けるために、バッチ入力 (つまり PIPE) でコマンド補完機能を無効にする可能性があります。コマンド補完は、実際には端末入力を必要とするインタラクティブな機能です。

ptyモジュールをチェックアウトし、マスター/スレーブのペアをサブプロセスのパイプとして使用してみてください。

于 2013-01-28T15:52:59.240 に答える
2

タブキーをパイプに送信するようなことは実際にはありません。パイプはビットの文字列のみを受け入れることができ、タブ文字がそれを行っていない場合、解決策がない可能性があります。

pexpectと呼ばれる同様のことを行うプロジェクトがあります。そのinteract()コードを見るだけで、それを機能させる明らかなものは見当たりませんが、あなたのコードは機能しません。それを考えると、最も可能性の高い説明は、pexpectが実際にそれ自体を疑似端末のように見せるために何らかの作業を行うということです。おそらく、そのためのコードを組み込むことができますか?

于 2013-01-28T15:46:36.907 に答える
1

isedev's answerに基づいて、コードを次のように変更しました。

import os, pty

def get_cli_subprocess_handle():
    masterPTY, slaveTTY = pty.openpty()
    return masterPTY, slaveTTY, subprocess.Popen(
                                                 '/bin/myshell',
                                                 shell=False,
                                                 stdin=slaveTTY,
                                                 stdout=slaveTTY,
                                                 stderr=slaveTTY,
                                                 )

この返されたタプルを使用して、必要に応じてselect.select([masterPTY],[],[])andを実行することができos.read(masterPTY, 1024)、pty モジュール ソースのプライベート メソッドと非常によく似た関数を使用して master-pty に書き込みました。

def write_all(masterPTY, data):
    """Successively write all of data into a file-descriptor."""
    while data:
        chars_written = os.write(masterPTY, data)
        data = data[chars_written:]
    return data

良い解決策をありがとう。この例が他の人に役立つことを願っています。:)

于 2013-01-29T17:45:54.923 に答える