pty --- 偽終端工具?
源代碼: Lib/pty.py
pty 模塊定義了一些處理“偽終端”概念的操作:啟動另一個進程并能以程序方式在其控制終端中進行讀寫。
由于偽終端處理高度依賴于具體平臺,因此此功能只有針對 Linux 的代碼。 (Linux 代碼也可在其他平臺上工作,但是未經測試。)
pty 模塊定義了下列函數:
-
pty.fork()? 分叉。 將子進程的控制終端連接到一個偽終端。 返回值為
(pid, fd)。 請注意子進程獲得 pid 0 而 fd 為 invalid。 父進程返回值為子進程的 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 信號則 spawn 可能將永不返回,除非在你的平臺上當傳入三個空列表時 select 會拋出一個錯誤。 這是一個程序缺陷,相關文檔見 問題 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)
