:mod:`!pty` --- Pseudo-terminal utilities
=========================================

.. module:: pty
   :synopsis: Pseudo-Terminal Handling for Unix.

**Source code:** :source:`Lib/pty.py`

--------------

The :mod:`!pty` module defines operations for handling the pseudo-terminal
concept: starting another process and being able to write to and read from its
controlling terminal programmatically.

.. availability:: Unix.

Pseudo-terminal handling is highly platform dependent. This code is mainly
tested on Linux, FreeBSD, and macOS (it is supposed to work on other POSIX
platforms but it's not been thoroughly tested).

The :mod:`!pty` module defines the following functions:


.. function:: fork()

   Fork. Connect the child's controlling terminal to a pseudo-terminal. Return
   value is ``(pid, fd)``. Note that the child  gets *pid* 0, and the *fd* is
   *invalid*. The parent's return value is the *pid* of the child, and *fd* is a
   file descriptor connected to the child's controlling terminal (and also to the
   child's standard input and output).

   The returned file descriptor *fd* is :ref:`non-inheritable <fd_inheritance>`.

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

   .. versionchanged:: 3.15
      The returned file descriptor is now made non-inheritable.


.. function:: openpty()

   Open a new pseudo-terminal pair, using :func:`os.openpty` if possible, or
   emulation code for generic Unix systems. Return a pair of file descriptors
   ``(master, slave)``, for the master and the slave end, respectively.


.. function:: spawn(argv[, master_read[, stdin_read]])

   Spawn a process, and connect its controlling terminal with the current
   process's standard io. This is often used to baffle programs which insist on
   reading from the controlling terminal. It is expected that the process
   spawned behind the pty will eventually terminate, and when it does *spawn*
   will return.

   A loop copies STDIN of the current process to the child and data received
   from the child to STDOUT of the current process. It is not signaled to the
   child if STDIN of the current process closes down.

   The functions *master_read* and *stdin_read* are passed a file descriptor
   which they should read from, and they should always return a byte string. In
   order to force spawn to return before the child process exits an
   empty byte array should be returned to signal end of file.

   The default implementation for both functions will read and return up to 1024
   bytes each time the function is called. The *master_read* callback is passed
   the pseudoterminal’s master file descriptor to read output from the child
   process, and *stdin_read* is passed file descriptor 0, to read from the
   parent process's standard input.

   Returning an empty byte string from either callback is interpreted as an
   end-of-file (EOF) condition, and that callback will not be called after
   that. If *stdin_read* signals EOF the controlling terminal can no longer
   communicate with the parent process OR the child process. Unless the child
   process will quit without any input, *spawn* will then loop forever. If
   *master_read* signals EOF the same behavior results (on linux at least).

   Return the exit status value from :func:`os.waitpid` on the child process.

   :func:`os.waitstatus_to_exitcode` can be used to convert the exit status into
   an exit code.

   .. audit-event:: pty.spawn argv pty.spawn

   .. versionchanged:: 3.4
      :func:`spawn` now returns the status value from :func:`os.waitpid`
      on the child process.

Example
-------

The following program acts like the Unix command :manpage:`script(1)`, using a
pseudo-terminal to record all input and output of a terminal session in a
"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)
