subprocess communication, exec()

Chuckk Hubbard badmuthahubbard at gmail.com
Tue Nov 11 16:12:21 EST 2008


On Tue, Nov 11, 2008 at 9:39 PM, Jeff McNeil <jeff at jmcneil.net> wrote:
> 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

That helps immensely, Jeff, thank you for explaining all that.  I took
out 'shell=True' and it works, and I took out the stdout and stderr
arguments to debug. I am finally able to perform every step in my
plan: start a child process of python running a script that imports
the Csound API; raise the nice level of the parent process; compile
and run a Csound orchestra remotely; and send it notes from the parent
process.
Thanks for your help.
-Chuckk

-- 
http://www.badmuthahubbard.com



More information about the Python-list mailing list