ptyPseudo-terminal utilities伪终端实用程序

Source code: Lib/pty.py


The pty module defines operations for handling the pseudo-terminal concept: starting another process and being able to write to and read from its controlling terminal programmatically.pty模块定义了处理伪终端概念的操作:启动另一个进程,并能够以编程方式对其控制终端进行写入和读取。

Pseudo-terminal handling is highly platform dependent. 伪终端处理高度依赖于平台。This code is mainly tested on Linux, FreeBSD, and macOS (it is supposed to work on other POSIX platforms but it’s not been thoroughly tested).这段代码主要在Linux、FreeBSD和macOS上测试(它本应在其他POSIX平台上工作,但尚未经过彻底测试)。

The pty module defines the following functions:pty模块定义了以下功能:

pty.fork()

Fork. Connect the child’s controlling terminal to a pseudo-terminal. Return value is (pid, fd). 将孩子的控制终端连接到一个伪终端。返回值为(pid, fd)Note that the child gets pid 0, and the fd is invalid. 请注意,子级的pid为0,fd无效。The parent’s return value is the pid of the child, and fd is a file descriptor connected to the child’s controlling terminal (and also to the child’s standard input and output).父级的返回值是子级的pidfd是连接到子级的控制终端(以及子级的标准输入和输出)的文件描述符。

pty.openpty()

Open a new pseudo-terminal pair, using os.openpty() if possible, or emulation code for generic Unix systems. Return a pair of file descriptors (master, slave), for the master and the slave end, respectively.如果可能的话,使用os.openpty()或通用Unix系统的仿真代码打开一个新的伪终端对。返回一对文件描述符(master, slave),分别用于master和slave端。

pty.spawn(argv[, master_read[, stdin_read]])

Spawn a process, and connect its controlling terminal with the current process’s standard io. 生成一个进程,并将其控制终端与当前进程的标准io连接。This is often used to baffle programs which insist on reading from the controlling terminal. 这通常被用来阻碍那些坚持从控制终端读取的程序。It is expected that the process spawned behind the pty will eventually terminate, and when it does spawn will return.预计pty后面产生的进程最终将终止,当它产生时将返回。

A loop copies STDIN of the current process to the child and data received from the child to STDOUT of the current process. 循环将当前进程的STDIN复制到子进程,并将从子进程接收的数据复制到当前进程的STD输出。It is not signaled to the child if STDIN of the current process closes down.如果当前进程的STDIN关闭,则不会向子进程发出信号。

The functions master_read and stdin_read are passed a file descriptor which they should read from, and they should always return a byte string. 函数master_readstdin_read传递了一个文件描述符,它们应该从中读取,并且它们应该始终返回一个字节字符串。In order to force spawn to return before the child process exits an empty byte array should be returned to signal end of file.为了在子进程退出之前强制生成返回,应该将空字节数组返回到文件末尾。

The default implementation for both functions will read and return up to 1024 bytes each time the function is called. 每次调用函数时,这两个函数的默认实现将读取并返回最多1024个字节。The master_read callback is passed the pseudoterminal’s master file descriptor to read output from the child process, and stdin_read is passed file descriptor 0, to read from the parent process’s standard input.master_read回调传递伪终端的主文件描述符以读取子进程的输出,stdin_read传递文件描述符0以读取父进程的标准输入。

Returning an empty byte string from either callback is interpreted as an end-of-file (EOF) condition, and that callback will not be called after that. 从任一回调返回一个空字节字符串将被解释为文件结束(EOF)条件,此后将不会调用该回调。If stdin_read signals EOF the controlling terminal can no longer communicate with the parent process OR the child process. 如果stdin_read发出EOF信号,则控制终端不能再与父进程或子进程通信。Unless the child process will quit without any input, spawn will then loop forever. 除非子进程在没有任何输入的情况下退出,否则派生将永远循环。If master_read signals EOF the same behavior results (on linux at least).如果master_read向EOF发出相同的行为结果(至少在linux上)。

Return the exit status value from os.waitpid() on the child process.从子进程上的os.waitpid()返回退出状态值。

waitstatus_to_exitcode() can be used to convert the exit status into an exit code.可以用于将退出状态转换为退出代码。

Raises an auditing event pty.spawn with argument argv.使用参数argv引发审核事件pty.spawn

Changed in version 3.4:版本3.4中更改: spawn() now returns the status value from os.waitpid() on the child process.现在从子进程上的os.waitpid()返回状态值。

Example实例

The following program acts like the Unix command script(1), using a pseudo-terminal to record all input and output of a terminal session in a “typescript”.以下程序的作用类似于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)