subprocess communication, exec()

Jeff McNeil jeff at jmcneil.net
Tue Nov 11 14:39:19 EST 2008


On Nov 11, 1:23 pm, "Chuckk Hubbard" <badmuthahubb... at gmail.com>
wrote:
> If I run 'python -i subprocessclient.py' I expect to see the nice
> level of it go up 2, and the nice level of the subprocess go up 1.
> But all I see is the nice level of the client change.  What am I doing
> wrong?
>
> subprocessserver.py:
> ----------------------------
> #!/usr/bin/python2.5
>
> import os
> import sys
>
> while True:
>     next_line = sys.stdin.readline()
>     if not next_line:
>         break
>     exec(next_line)
> #    sys.stdout.write(output)
> #    sys.stdout.write(next_line)
> #    sys.stdout.flush()
> ----------------------------
>
> subprocessclient.py:
> ----------------------------
> #!/usr/bin/python2.5
>
> import subprocess, os
>
> server = subprocess.Popen(('python2.5', 'subprocessserver.py'),
> shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
> stderr=subprocess.PIPE)
>
> os.nice(2)
>
> server.stdin.write('''os.nice(1)''')
> ----------------------------
>
> Thanks.
> -Chuckk
>
> --http://www.badmuthahubbard.com

Looks like you're dropping an error by redirecting the child process'
standard error into a pipe.

First off, remove the stderr=subprocess.PIPE from
subprocessclient.py.  When you do so, you'll start seeing an error
message whenever your code runs:

[jeff at marvin ~]$ python client.py
None
[jeff at marvin ~]$ Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined

That doesn't make a lot of sense at first, until you consider the
following:

[jeff at marvin ~]$ echo 'os.nice(1)' | python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined

The Python interpreter is trying to execute the data you write to the
stdin of the child process.  Changing the Popen line to use the string
form rather than the sequence form remedies the problem, as does
changing 'string=True' to 'string=False.'

The reason? Because when you set shell=True, additional arguments in
args sequence are passed as additional arguments to the shell itself,
not to the command.

>From subprocess.py:

    if isinstance(args, types.StringTypes):
        args = [args]
    else:
        args = list(args)

    if shell:
        args = ["/bin/sh", "-c"] + args

So, in your attempt, you're effectively doing the following:

/bin/sh -c "python2.5" "server.py"

When you want:

/bin/sh -c "python2.5 server.py"

HTH,

Jeff



More information about the Python-list mailing list