Python pty.fork - how it works

http://docs.python.org/library/pty.html says -

pty.fork () ΒΆ Fork. Connect the control terminal for children to the pseudo-terminal. Return value (pid, fd). Note that the child receives pid 0, and fd is not valid. The value returned by the parents is the pid of the child, and fd is the file descriptor connected to the control terminal for the children (as well as to the standard inputs and outputs of the childs).

What does it mean? Each process has 3 fd (stdin, stdout, stderr). Does it affect these fds now? will the child process not have any of these fds? I'm confused. - completely.

+6
python pty
source share
4 answers

I think I finally got a minimal example for pty.fork in Python - and since it was very difficult for me to find a similar example, I am posting it here as an illustration of @joni's answer. It is based mainly on:

Particularly unpleasant bits are the documentation, which still refers to master_open() , which is deprecated; and the fact that pty.fork will not spawn a child process if the file descriptor (returned by the fork method) is not read by the parent process! (note that there is os.fork such requirement in os.fork ). It also seems that os.fork bit more portable (read a few comments, noting that pty.fork does not work on some platforms).

In any case, here is the first script ( pyecho.py ), which acts as an executable file (it just reads the lines from standard input and writes them back in upper case):

 #!/usr/bin/env python # pyecho.py import sys; print "pyecho starting..." while True: print sys.stdin.readline().upper() 

... and now, here is the actual script (this would require pyecho.py to be in the same directory):

 #!/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 (ie 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() 

Ok, hope this helps someone
Hooray!

+11
source share

The main point of using pty.fork () is that the returned pseudo-terminal (pty) file descriptor can be used to communicate with the generated process differently, i.e. by directly writing and reading from its (pseudo) terminal, and not from stdin / out / err.

There is also additional information about pty and tty (from StackOverflow) and a link to a simple example of using pty.fork () .

+3
source share

", and fd is the file descriptor connected to the childs control terminal β†’> The child process will not see any difference, it will be able to properly access the stdin / out standard (I do not know about stderr). The only difference is that on the other hand," pipe "is not a terminal where the user reads / enters text, but the parent process that can be accessed by returning fd.

+2
source share

Thanks Joni.Here is what I understood. When pty.fork () is called. the parent process is associated with the ptmx master. the parent will wait for keyboard input or data from the wizard.

the child closes its stdin, stdout and stderr. And duplicates the stdin slaves, stdout.stderr. now the child is running the program (say bc). The program expects input when you enter 1 + 1 - it is passed to the master (remember that the child and the slave have some stdin, stdout, stderr) using child / slave. the master calculates its answer "2" and writes to stdout-, since the parent waits for data from master -it, selects "2" and writes to stdout.

I came to this conclusion after going through some good old programs on the pseudo-terminal :) I do not think that the python logic will not differ from them. Hth someone.

0
source share

All Articles