1

Possibly a duplicate of How to start a background process in Python?

But out of many solutions, only os.system(commandToRunInBackground &) seems to be simple and do the trick. Though, according to Replacing os.system(), using subprocess module is more recommended. So how to run background process in terms of shell (note, & at the end) using subprocess module.

rok
  • 9,403
  • 17
  • 70
  • 126
  • 2
    Since `subprocess.Popen` is non-blocking, why you would want to background a system call made using it? – Zev Averbach Jun 21 '17 at 14:28
  • As Zev says -- why do you think you need this, as opposed to the *default* behavior of your `subprocess.Popen()`-invoked command running in the background? – Charles Duffy Jun 21 '17 at 15:25
  • 1
    `subprocess.Popen` has no equivalent to the shell's `&` operator because there's no option to call `setpgid(0, 0)` in the child process to create a new group that's in the background. Without that, if the process reads from the terminal via stdin, the terminal won't stop it via `SIGTTIN` since it's still in the foreground process group. – Eryk Sun Jun 21 '17 at 18:55
  • the reason for using `os.system` is that original syntax with `&` may be specified – rok Jun 22 '17 at 10:28
  • There's an indirect alternative. Set the `preexec_fn` parameter to a function that calls `setpgid(0, 0)`. Then you can check if it was stopped by the terminal via `pid, status = os.waitpid(proc.pid, os.WUNTRACED);` `if os.WIFSTOPPED(status): sig = os.WSTOPSIG(status)`. This will be `signal.SIGTTIN` if it was stopped to prevent reading from the terminal, or `signal.SIGTTOU` if stopped to prevent writing. Usually the terminal is configured to allow a background process to write to it. – Eryk Sun Jun 22 '17 at 13:59

1 Answers1

2

In modern operating systems, processes naturally run in parallel, and having one waiting for the termination of another is the special case. When the & syntax was designed in the late 60's this was different. Then you had to mark a parallel execution.

On a shell this sticks up to today, also because it is convenient in many cases to have the shell wait for the termination of a command before allowing the next input from the user, so there still is the case without & waiting for the termination.

On the programming level the case with the & (parallel execution) is the normal case and nothing has to be done to achieve it.

The case without the & (waiting for termination) can be achieved by using the wait() system call explicitly (this is what the shell does in most cases).

For you, just use Popen and don't call wait() ;-)

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • 1
    It is worth mentioning that subprocess.Popen does not run the shell by default. It accepts a list: `[program, arg1, arg2]` (to see an example, call `shlex.split(cmd)`) – jfs Jun 21 '17 at 15:11
  • Right. When OP considered using `&` they might expect a shell interpretation step for other stuff as well. – Alfe Jun 21 '17 at 15:13
  • I agree with you for the way to just use `Popen`, but not on the fact that sequential execution is only a deprecated feature from the 60's. The shells use by default sequential execution precisely to allow the input of many commands at the same time (for example from a file) while allowing each command to use the results produced in the previous one. – Serge Ballesta Jun 21 '17 at 15:14
  • I wouldn't call it a 'deprecated feature' from the 60s. But the early OSes first knew sequential operation only (but already had a command line), _then_ came the parallel execution stuff. To achieve this on the command line one had to add something (the `&`) as a marker for this. – Alfe Jun 21 '17 at 15:17