pty — Псевдотерминальные утилиты

Исходный код: Lib/pty.py.


Модуль pty определяет операции для работы с концепцией псевдотерминала: запуск другого процесса и возможность программно записывать на управляющий терминал и читать с него.

Работа с псевдотерминалами сильно зависит от платформы. Этот код в основном протестирован на Linux, FreeBSD и macOS (предполагается, что он будет работать и на других POSIX-платформах, но это не было тщательно протестировано).

Модуль 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 вернется.

Цикл копирует STDIN текущего процесса в дочерний, а данные, полученные от дочернего, в STDOUT текущего процесса. Если STDIN текущего процесса закрывается, дочерний процесс не получает сигнала.

Функциям master_read и stdin_read передается дескриптор файла, из которого они должны читать, и они всегда должны возвращать байтовую строку. Для того чтобы заставить spawn вернуться до выхода дочернего процесса, следует возвращать пустой массив байтов, сигнализирующий о конце файла.

Реализация по умолчанию для обеих функций будет считывать и возвращать до 1024 байт при каждом вызове функции. Обратному вызову master_read передается дескриптор главного файла псевдотерминала для чтения вывода из дочернего процесса, а stdin_read передается дескриптор файла 0 для чтения из стандартного ввода родительского процесса.

Возвращение пустой строки байтов из любого обратного вызова интерпретируется как условие конца файла (EOF), после чего этот обратный вызов вызываться не будет. Если stdin_read сигнализирует EOF, управляющий терминал больше не может взаимодействовать с родительским процессом ИЛИ дочерним процессом. Если дочерний процесс не выйдет без какого-либо ввода, то spawn будет циклиться вечно. Если master_read подаст сигнал EOF, то поведение будет таким же (по крайней мере, в linux).

Возвращает значение статуса выхода из os.waitpid() на дочернем процессе.

waitstatus_to_exitcode() можно использовать для преобразования статуса выхода в код выхода.

Вызывает auditing event pty.spawn с аргументом argv.

Изменено в версии 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)
Вернуться на верх