pty — Утилиты псевдотерминалов
Исходный код: Lib/pty.py
Модуль pty определяет операции для обработки понятия псевдотерминала: запуск другого процесса и возможность программно писать в него и читать из него.
Обработка псевдотерминалов сильно зависит от платформы. Этот код в основном тестировался на Linux, FreeBSD и macOS (предполагается, что он будет работать на других POSIX-платформах, но он не был полностью протестирован).
Модуль pty определяет следующие функции:
-
pty.fork() -
Вызов
fork. Подключает управляющий терминал дочернего процесса к псевдотерминалу. Значение возврата —(pid, fd). Обратите внимание, что у дочернего процесса pid равен 0, а fd — недействителен. Значение возврата для родительского процесса — pid дочернего процесса, а fd — дескриптор файла, подключенный к управляющему терминалу дочернего процесса (а также к стандартному вводу и выводу дочернего процесса).
-
pty.openpty() -
Открывает новую пару псевдотерминалов, используя
os.openpty(), если возможно, или код эмуляции для общих Unix-систем. Возвращает пару дескрипторов файлов(master, slave), для мастер- и слев-концов, соответственно.
-
pty.spawn(argv[, master_read[, stdin_read]]) -
Запускает процесс и подключает его управляющий терминал к стандартным потокам ввода-вывода текущего процесса. Это часто используется для обфускации программ, которые настаивают на чтении из управляющего терминала. Ожидается, что процесс, запущенный через pty, в конечном итоге завершится, и при этом spawn вернет значение.
Цикл копирует стандартный ввод текущего процесса в дочерний процесс, а данные, полученные от дочернего процесса, в стандартный вывод текущего процесса. Если стандартный ввод текущего процесса закрывается, дочернему процессу об этом не сигнализируется.
Функциям master_read и stdin_read передается дескриптор файла, из которого они должны читать, и они всегда должны возвращать строку байтов. Для принудительного возврата spawn перед завершением дочернего процесса должна быть возвращена пустая строка байтов, сигнализирующая об окончании файла.
Базовая реализация обеих функций будет читать и возвращать до 1024 байтов каждый раз, когда функция вызывается. Обратно вызываемому callback master_read передается мастер-дескриптор псевдотерминала для чтения вывода дочернего процесса, а stdin_read передается дескриптор файла 0 для чтения из стандартного ввода родительского процесса.
Возврат пустой строки байтов из любого callback интерпретируется как условие конца файла (EOF), и после этого этот callback больше не будет вызываться. Если stdin_read сигнализирует об EOF, управляющий терминал больше не может общаться с родительским процессом ИЛИ с дочерним процессом. Если дочерний процесс не выйдет без каких-либо данных, spawn будет зацикливаться. Если master_read сигнализирует об EOF, наблюдается аналогичное поведение (по крайней мере, в Linux).
Возвращает значение кода выхода из
os.waitpid()для дочернего процесса.waitstatus_to_exitcode()может быть использован для преобразования кода выхода в код завершения.Вызывает событие аудита
pty.spawnс аргументомargv.Изменено в версии 3.4:
spawn()теперь возвращает значение статуса изos.waitpid()для дочернего процесса.
Пример
Следующая программа работает как команда Unix script(1), используя псевдотерминал для записи всего ввода и вывода сеанса терминала в «протокол».
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)
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/pty.html