# `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.

Availability: Unix.

El manejo de pseudo-terminales depende en gran medida de la plataforma. Este código se prueba principalmente en Linux, FreeBSD y macOS (se supone que funciona en otras plataformas POSIX, pero no se ha probado a fondo).

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)

  Advertencia

  On macOS the use of this function is unsafe when mixed with using higher-level system APIs, and that includes using `urllib.request`.

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á.

  Un bucle copia STDIN del proceso actual al hijo y los datos recibidos del niño a STDOUT del proceso actual. No se le indica al hijo si STDIN del proceso actual se cierra.

  A las funciones master_read y stdin_read se les pasa un descriptor de archivo del cual deben leer, y siempre deben retornar una cadena de bytes. Para forzar el retorno de spawn antes de que el proceso hijo salga, se debe retornar un arreglo de bytes vacía para señalar el final del archivo.

  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)

  Retorna el valor del estado de salida de `os.waitpid()` en el proceso hijo.

  `os.waitstatus_to_exitcode()` se puede utilizar para convertir el estado de salida en un código de salida.

  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)