pty —伪终端 Util

源代码: Lib/pty.py


pty模块定义用于处理伪终端概念的操作:启动另一个进程,并能够以编程方式对其控制终端进行读写。

由于伪终端处理高度依赖平台,因此有代码仅适用于 Linux。 (Linux 代码应该可以在其他平台上运行,但是尚未经过测试.)

pty模块定义以下Function:

  • pty. fork ( )

    • 叉子。将孩子的控制终端连接到伪终端。返回值为(pid, fd)。请注意,孩子的* pid 为 0,而 fd invalid 。父级的返回值是子级的 pid fd *是连接到子级控制终端(以及子级的标准 Importing 和输出)的文件 Descriptors。
  • pty. openpty ( )

    • 打开一个新的伪终端对,如果可能的话,使用os.openpty()或通用 Unix 系统的仿真代码。返回分别用于主端和从端的Pair文件 Descriptors(master, slave)
  • pty. spawn(* argv * [,* master_read * [,* stdin_read *]])

    • 生成一个进程,并将其控制终端与当前进程的标准 io 连接。这通常用于使必须从控制终端读取的程序变得混乱。预期 pty 后面产生的进程finally将终止,并且当它完成时* spawn *将返回。

向函数* master_read stdin_read *传递了一个文件 Descriptors,应从中读取文件 Descriptors,并且它们应始终返回字节字符串。为了在子进程退出之前强制生成返回,应该抛出OSError

每次调用该函数时,这两个函数的默认实现都会读取并返回多达 1024 个字节。 * master_read 回调传递给伪终端的主文件 Descriptors,以从子进程中读取输出, stdin_read *传递给文件 Descriptors0,以从父进程的标准 Importing 中读取。

从任一回调返回空字节字符串都被解释为文件结束(EOF)条件,此后将不再调用该回调。如果* stdin_read 发出 EOFsignal,则控制终端无法再与父进程或子进程通信。除非子进程在没有任何 Importing 的情况下退出,否则 spawn 将永远循环。如果 master_read *发出 EOFsignal,则表示相同的行为(至少在 Linux 上)。

如果两个回调均指示 EOF,则* spawn 可能永远不会返回,除非 select *在传递三个空列表时在您的平台上引发错误。这是一个错误,记录在issue 26228中。

用参数argv引发auditing event pty.spawn

在版本 3.4 中进行了更改:spawn()现在在子进程上从os.waitpid()返回状态值。

Example

下面的程序就像 Unix 命令* script(1) *一样,使用伪终端在“typing 稿”中记录终端会话的所有 Importing 和输出。

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)