views:

988

answers:

2

I'm uncertain whether to use pty.fork() or os.fork() when spawning external background processes from my app. (Such as chess engines)

I want the spawned processes to die if the parent is killed, as with spawning apps in a terminal.

What are the ups and downs between the two forks?

+3  A: 

In the past I've always used the subprocess module for this. It provides a good api for communicating with subprocesses.

You can use call(*popenargs, **kwargs) for blocking execution of them, and I believe using the Popen class can handle async execution.

Check out the docs for more info.

As far as using os.fork vs pty.fork, both are highly platform dependent, and neither will work (or at least is tested) with windows. The pty module seems to be the more constrained of the two by reading the docs. The main difference being the pseudo terminal aspect. So if you aren't willing to architect your code in such a way as to be able to use the subprocess module, I'd probably go with os.fork instead of pty.fork.

Bryan McLemore
Actually it is exactly the 'pseudo terminal aspect' I would like to know more about. I've read many of the kernel docs and mans, but I haven't found out exactly when I am supposed to use witch..
Thomas Ahle
From the reading I've done it talks about being able to do input/output to the terminal of the process via code. So this to me sounds like a separate paradigm from using stdout/stdin to communicate with the application. More info on the pseudo terminal concept here: http://en.wikipedia.org/wiki/Pseudo_terminal
Bryan McLemore
When I read wikipedia, the pseudo-terminal seams like just an alternative to pipes.When you say 'do input/output via code', do you mean stuff like delete and inset, or just standard read/write like a pipe?
Thomas Ahle
+5  A: 

The child process created with os.fork() inherits stdin/stdout/stderr from parent process, while the child created with pty.fork() is connected to new pseudo terminal. You need the later when you write a program like xterm: pty.fork() in parent process returns a descriptor to control terminal of child process, so you can visually represent data from it and translate user actions into terminal input sequences.

Update:

From pty(7) man page:

A process that expects to be connected to a terminal, can open the slave end of a pseudo-terminal and then be driven by a program that has opened the master end. Anything that is written on the master end is provided to the process on the slave end as though it was input typed on a terminal. For example, writing the interrupt character (usually control-C) to the master device would cause an interrupt signal (SIGINT) to be generated for the foreground process group that is connected to the slave. Conversely, anything that is written to the slave end of the pseudo-terminal can be read by the process that is connected to the master end.

Denis Otkidach
So the purpose of the pty is to keep the child IO in a separate box, instead of mixing it up with the parents stdin/out? I suppose you could do the same with os.fork and some pibes.Does this terminal do anything else than IO?
Thomas Ahle
Sure, you can implement `pty.fork()` using `pty.openpty()` and `os.fork()` (actually you can see it in `pty.py` source). But pseudo-terminal differ from pipes, see http://en.wikipedia.org/wiki/Pseudo_terminal.
Denis Otkidach
In pty.py I see that even the non os.forkpty code in pty.fork uses the /dev/pty device, so there must be more to it than just a paradigm of input/output. I read the comments in the top of the file, and they say: "Bugs: No signal handling. Doesn't set slave termios and window size". Wikipedia said nothing about pty's doing stuff like that..
Thomas Ahle