2

I want to execute an arbitrary user-provided command in that user's $SHELL. The command may be short-lived (like ls) or long-lived (like firefox), and it may be a single command, a pipeline, or any other shell-supported construct.

The method of execution must indicate success or failure on behalf of the shell and must not block regardless of when or whether the command terminates. The command may never terminate until the method of execution returns and my program continues.

Popen() with shell=True does not block but also does not indicate failure. The subprocess helper functions do block and are not useful here. Popen.poll() (suggested in this question) returns None until the command terminates and does not immediately return non-None on failure (it must be called repeatedly until the shell terminates).

As an example of the desired behavior

prog1 = shell_run('blocking_prog', stdin=PIPE, stdout=PIPE)
prog2 = shell_run('nonsense_prog', stdin=PIPE, stdout=PIPE)

the first line should assign a Popen object to prog1, the second line should raise an OSError or similar.

Am I correct in thinking that it is impossible to reliably detect Popen() errors under these conditions?

Community
  • 1
  • 1
yew
  • 55
  • 2
  • 5
  • 1
    I'm not sure I understand your *actual problem*. What do you want to do? Why is something like `subprocess.check_call('date', shell=True)` not sufficient? – phihag Mar 06 '13 at 00:13
  • you can do [Non-blocking read on a subprocess.PIPE in python](http://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python) to get stderr output but it is unclear whether you actually need it. – jfs Mar 06 '13 at 11:58
  • It's not clear still whether the point of your question is to tell whether the shell failed to execute a command, or how to use .communicate(), or what situation you're talking about. – the paul Mar 07 '13 at 20:03
  • +1. Quite concise and detailed answer with quite nothing to complain. – glglgl Aug 16 '13 at 07:07
  • @phihag Probably because of the `PIPE`s. – glglgl Aug 16 '13 at 07:08

2 Answers2

1

I'm not answering your question directly, but using plumbum for such tasks can make your life so much easier. http://plumbum.readthedocs.org/en/latest/

shx2
  • 61,779
  • 13
  • 130
  • 153
0

If you'll have to know if it failed in order to know whether to pipe data in or not, you could do

prog2 = shell_run('nonsenseprog', stdin=PIPE, stdout=PIPE,
               shell=True, executable=os.getenv('SHELL'))
# If the program does not exist, it should fail immediately and .poll() knows about that.
# If it exists and runs, `.poll()` returns None.
if prog2.poll() is not None:
    raise Whatever # it failed

Alternatively, you could check if you really need shell=True.

glglgl
  • 89,107
  • 13
  • 149
  • 217