2010-10-26 18 views
6

http://docs.python.org/library/pty.html dice -pitón pty.fork - ¿cómo funciona

pty.fork() ¶ Tenedor. Conecte el terminal de control del niño a un pseudo-terminal. El valor de retorno es (pid, fd). Tenga en cuenta que el niño obtiene pid 0, y el fd no es válido. El valor de retorno del padre es el pid del niño y fd es un descriptor de archivo conectado al terminal de control del niño (y también a la entrada y salida estándar del niño).

¿Qué significa esto? Cada proceso tiene 3 fd (stdin, stdout, stderr). ¿Esto afecta estos fds ahora? ¿El proceso del niño no tendrá ninguno de estos fds? Estoy confundido. Totalmente.

Respuesta

2

"y fd es un descriptor de archivo conectado al terminal de control del niño" -> El proceso secundario no verá ninguna diferencia, podrá acceder normalmente a stdin/out (no sé sobre stderr). La única diferencia es que en el otro lado de la "tubería" no está una terminal donde un usuario está leyendo/escribiendo, pero el proceso principal al que puede acceder es el fd devuelto.

0

Gracias Joni.Here es lo que entendí.Cuando se invoca pty.fork(). el proceso principal está conectado al maestro de ptmx. el padre esperará la entrada del teclado o los datos del maestro.

niño cierra su stdin, stdout y stderr. Y duplica los esclavos stdin, stdout.stderr. ahora el niño ejecutó un programa (digamos bc). El programa está esperando la entrada, cuando escribe 1 + 1 - se pasa al maestro (recuerde que tanto el hijo como el esclavo tienen stdin, stdout, stderr) por niño/esclavo. maestro calcula su respuesta "2" y escribe en stdout- ya que el padre está esperando los datos de la maestra -elije "2" y escribe en stdout.

He llegado a esta conclusión después de revisar algunos buenos viejos programas c en pseudo-terminal :) No creo que la lógica de Python no sea diferente a ellos. HTH alguien.

11

Creo que finalmente obtuve un ejemplo mínimo para pty.fork en Python, y como me resulta extremadamente difícil encontrar un ejemplo similar, lo publico aquí como una ilustración de la respuesta de @ joni. Se basa esencialmente en:

Particularmente los bits desagradables están encontrando documentación que todavía se refiere a master_open() que está obsoleto; y el hecho de que pty.fork será no engendre un proceso hijo, a menos que el descriptor de archivo (devuelto por el método fork) sea leído por el proceso principal. (tenga en cuenta que en os.fork no existe tal requisito) Además, parece que os.fork es un poco más portátil (lea algunos comentarios que señalan que pty.fork no funciona en algunas plataformas).

De todas formas, aquí es primero un guión (pyecho.py) que actúa como un archivo ejecutable (que simplemente lee las líneas de la entrada estándar, y los escribe de nuevo en mayúsculas):

#!/usr/bin/env python 
# pyecho.py 

import sys; 

print "pyecho starting..." 

while True: 
    print sys.stdin.readline().upper() 

... y luego, aquí está el script (se requerirá que pyecho.py está en el mismo directorio):

#!/usr/bin/env python 

import sys 
import os 
import time 
import pty 

def my_pty_fork(): 

    # fork this script 
    try: 
    (child_pid, fd) = pty.fork() # OK 
    #~ child_pid, fd = os.forkpty()  # OK 
    except OSError as e: 
    print str(e) 

    #~ print "%d - %d" % (fd, child_pid) 
    # NOTE - unlike OS fork; in pty fork we MUST use the fd variable 
    # somewhere (i.e. in parent process; it does not exist for child) 
    # ... actually, we must READ from fd in parent process... 
    # if we don't - child process will never be spawned! 

    if child_pid == 0: 
    print "In Child Process: PID# %s" % os.getpid() 
    # note: fd for child is invalid (-1) for pty fork! 
    #~ print "%d - %d" % (fd, child_pid) 

    # the os.exec replaces the child process 
    sys.stdout.flush() 
    try: 
     #Note: "the first of these arguments is passed to the new program as its own name" 
     # so:: "python": actual executable; "ThePythonProgram": name of executable in process list (`ps axf`); "pyecho.py": first argument to executable.. 
     os.execlp("python","ThePythonProgram","pyecho.py") 
    except: 
     print "Cannot spawn execlp..." 
    else: 
    print "In Parent Process: PID# %s" % os.getpid() 
    # MUST read from fd; else no spawn of child! 
    print os.read(fd, 100) # in fact, this line prints out the "In Child Process..." sentence above! 

    os.write(fd,"message one\n") 
    print os.read(fd, 100)  # message one 
    time.sleep(2) 
    os.write(fd,"message two\n") 
    print os.read(fd, 10000)  # pyecho starting...\n MESSAGE ONE 
    time.sleep(2) 
    print os.read(fd, 10000)  # message two \n MESSAGE TWO 
    # uncomment to lock (can exit with Ctrl-C) 
    #~ while True: 
     #~ print os.read(fd, 10000) 


if __name__ == "__main__": 
    my_pty_fork() 

Bueno, espero que esto ayude a alguien,
Salud!

+0

Este código no funciona para mí. Aquí está la salida: http://pastebin.com/MjGUChTy –

3

El punto principal de usar pty.fork() es que el descriptor de archivo devuelto pseudoterminal (pty) se puede utilizar para comunicarse con el proceso generado de una manera diferente, es decir. a través de la escritura directa y la lectura desde su (pseudo-) terminal - en lugar de stdin/out/err.

También hay más información about pty's and tty's (de StackOverflow) y a link to a simple example of using pty.fork().