pty —疑似端末ユーティリティ—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/pty
移動先:案内検索

pty —疑似端末ユーティリティ

ソースコード: :source: `Lib / pty.py`



pty モジュールは、疑似端末の概念を処理するための操作を定義します。つまり、別のプロセスを開始し、プログラムで制御端末に読み書きできるようにします。

疑似端末の処理はプラットフォームに大きく依存するため、Linuxでのみ処理するコードがあります。 (Linuxコードは他のプラットフォームでも動作するはずですが、まだテストされていません。)

pty モジュールは、次の関数を定義します。

pty.fork()
フォーク。 子供の制御端末を疑似端末に接続します。 戻り値は(pid, fd)です。 子は pid 0を取得し、 fd無効であることに注意してください。 親の戻り値は子の pid であり、 fd は子の制御端末(および子の標準入出力)に接続されたファイル記述子です。
pty.openpty()
可能であれば os.openpty()を使用するか、汎用Unixシステムのエミュレーションコードを使用して、新しい疑似端末ペアを開きます。 マスター側とスレーブ側にそれぞれファイル記述子のペア(master, slave)を返します。
pty.spawn(argv[, master_read[, stdin_read]])

プロセスを生成し、その制御端末を現在のプロセスの標準ioに接続します。 これは、制御端末からの読み取りを要求するプログラムを妨害するためによく使用されます。 ptyの背後で生成されたプロセスは最終的に終了し、終了すると spawn が戻ると予想されます。

関数 master_read および stdin_read には、読み取る必要のあるファイル記述子が渡され、常にバイト文字列を返す必要があります。 子プロセスが終了する前にスポーンを強制的に戻すには、 OSError をスローする必要があります。

両方の関数のデフォルトの実装では、関数が呼び出されるたびに最大1024バイトが読み取られて返されます。 master_read コールバックには、疑似端末のマスターファイル記述子が渡されて子プロセスからの出力が読み取られ、 stdin_read にはファイル記述子0が渡されて、親プロセスの標準入力から読み取られます。

いずれかのコールバックから空のバイト文字列を返すことは、ファイルの終わり(EOF)条件として解釈され、そのコールバックはその後呼び出されません。 stdin_read がEOFに信号を送ると、制御端末は親プロセスまたは子プロセスと通信できなくなります。 子プロセスが入力なしで終了しない限り、 spawn は永久にループします。 master_read がEOFに信号を送ると、同じ動作が発生します(少なくともLinuxでは)。

両方のコールバックがEOFを通知する場合、 select が3つの空のリストを渡されたときにプラットフォームでエラーをスローしない限り、 spawn はおそらく返されません。 これはバグであり、 issue 26228 に記載されています。

バージョン3.4で変更: spawn()は、子プロセスの os.waitpid()からステータス値を返すようになりました。

次のプログラムは、Unixコマンド script(1)のように動作し、疑似端末を使用して、端末セッションのすべての入力と出力を「typescript」に記録します。

import argparse
import os
import pty
import sys
import time

parser = argparse.ArgumentParser()
parser.add_argument('-a', dest='append', action='store_true')
parser.add_argument('-p', dest='use_python', action='store_true')
parser.add_argument('filename', nargs='?', default='typescript')
options = parser.parse_args()

shell = sys.executable if options.use_python else os.environ.get('SHELL', 'sh')
filename = options.filename
mode = 'ab' if options.append else 'wb'

with open(filename, mode) as script:
    def read(fd):
        data = os.read(fd, 1024)
        script.write(data)
        return data

    print('Script started, file is', filename)
    script.write(('Script started on %s\n' % time.asctime()).encode())

    pty.spawn(shell, read)

    script.write(('Script done on %s\n' % time.asctime()).encode())
    print('Script done, file is', filename)