Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
287 views
in Technique[技术] by (71.8m points)

python pty.fork - how does it work

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

pty.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).

What's does this mean ? Every process has 3 fd (stdin,stdout,stderr). Does this affects these fds now ? will child process won't have any of these fds? I'm confused.--totally.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

Particularly nasty bits are finding documentation that still refers to master_open() which is obsolete; and the fact that pty.fork will not spawn a child process, unless the file descriptor (returned by the fork method) is read from by the parent process! (note that in os.fork there is no such requirement) Also, it seems that os.fork is a bit more portable (read a few comments noting that pty.fork doesn't work on some platforms).

Anyways, here's first a script (pyecho.py) that acts as an executable (it simply reads lines from standard input, and writes them back in uppercase):

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

import sys;

print "pyecho starting..."

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

... and then, here is the actual script (it will require that pyecho.py is 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 (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
")
    print os.read(fd, 100)        # message one
    time.sleep(2)
    os.write(fd,"message two
")
    print os.read(fd, 10000)      # pyecho starting...
 MESSAGE ONE
    time.sleep(2)
    print os.read(fd, 10000)      # message two 
 MESSAGE TWO
    # uncomment to lock (can exit with Ctrl-C)
    #~ while True:
      #~ print os.read(fd, 10000)


if __name__ == "__main__":
    my_pty_fork()

Well, hope this helps someone,
Cheers!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...