pty — Utilidades para Pseudo-terminal

Código Fuente: Lib/pty.py


El módulo pty define las operaciones para manejar el concepto de pseudo-terminal: iniciar otro proceso para poder escribir y leer desde su propia terminal mediante programación.

Debido a que el manejo de una pseudo-terminal depende en gran medida de la plataforma, este código es solo para Linux (se supone que el código de Linux funciona para otras plataformas, pero este aún no se ha probado)

El modulo pty define las siguientes funciones:

pty.fork()

Bifurcación. Conectar en su propia terminal (terminal hijo) una pseudo-terminal. El valor de retorno es (pid, fd). Tener en cuenta que la terminal hijo tiene como valor pid 0 y fd es invalid. El valor de retorno del padre es el pid del hijo, y fd es un descriptor de archivo conectado a la terminal hijo (también a la salida y entrada estándar de la terminal hijo)

pty.openpty()

Abre un nuevo par de pseudo-terminales, usando os.openpty(), o código de emulación para sistemas genéricos de Unix. Retorna un par de descriptores de archivo (master, slave), para el master y el slave respectivamente.

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

Genera un proceso conectado a su terminal con el io estándar del proceso actual. Esto se usa a frecuentemente para confundir programas que insisten en leer desde la terminal de control. Se espera que el proceso generado detrás de pty sea finalizado y cuando lo haga spawn se retornará.

Las funciones master_read y stdin_read se les envía como parámetro un descriptor de archivo y siempre deben retornar una cadena de bytes. A fin de que se obligue a spawn a retornar antes que el proceso hijo salga se debe lanzar un OSError.

La implementación predeterminada para ambas funciones retornará hasta 1024 bytes cada vez que se llamen. El dato retornado de master_read se pasa al descriptor de archivo maestro para leer la salida del proceso hijo, y stdin_read pasa el descriptor de archivo 0, para leer desde la entrada del proceso padre.

Retornando una cadena de bytes vacía de cualquier llamado es interpretado como una condición de fin de archivo (EOF), y el llamado no se realizará después de eso. Si stdin_read retorna EOF la terminal de control ya no puede comunicarse con el proceso padre o el proceso hijo. A menos que el proceso hijo se cierre sin ninguna entrada spawn se repetirá para siempre. Si master_read retorna EOF se produce el mismo comportamiento (al menos en Linux)

Si ambas retrollamadas retornan EOF entonces spawn probablemente nunca retorne algo, a menos que select entregue un error en su plataforma cuando pasan tres listas vacías. Esto es un error documentado en issue 26228.

Lanza un evento de auditoria pty.spawn con el argumento argv.

Distinto en la versión 3.4: spawn() ahora retorna el valor de estado de os.waitpid() para los procesos hijos.

Ejemplo

El siguiente programa actúa como el comando de Unix script(1), usando una pseudo-terminal para registrar todas las entradas y salidas de una sesión en «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)