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?

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? Commented Mar 6, 2013 at 0:13
  • you can do Non-blocking read on a subprocess.PIPE in python to get stderr output but it is unclear whether you actually need it. Commented Mar 6, 2013 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. Commented Mar 7, 2013 at 20:03
  • +1. Quite concise and detailed answer with quite nothing to complain. Commented Aug 16, 2013 at 7:07
  • @phihag Probably because of the PIPEs. Commented Aug 16, 2013 at 7:08

2 Answers 2

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/

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.