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!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…