Using subprocess module to launch a shell shell script that itself forks a process
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Wed Oct 8 22:10:31 EDT 2008
En Wed, 08 Oct 2008 15:24:39 -0300, Samuel A. Falvo II
<sam.falvo at gmail.com> escribió:
> On Oct 7, 6:23 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar> wrote:
>> you set stdin=PIPE - is your java process expecting some input? you're
>> not writing anything to stdin.
>
> It does not expect input from stdin. However, this does not affect
> any OTHER scripts or commands I run.
But it *does* affect how subprocess handles the child process internally.
> Let's remember to look at the objective facts: for shell scripts that
> launch child processes of their own, Python hangs. For all other
> types of commands, it works 100% as expected.
Don't conclude too fast... I've tested a variant (using a Perl script as a
replacement instead of a Java program), and it worked fine:
<log>
gabriel at sleipnir:~$ cat foo.sh
#!/bin/sh
perl foo.pl&
echo End of foo.sh
gabriel at sleipnir:~$ cat foo.pl
#!/usr/bin/perl
for ($i=5; $i>0; $i--) {
print "$i seconds remaining...\n";
sleep(1);
}
print "End of foo.pl\n";
gabriel at sleipnir:~$ cat foo.py
#!/usr/bin/python2.5
import subprocess
command = "./foo.sh"
p = subprocess.Popen(command,
shell=True,
stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
close_fds=True
)
print "py: before p.communicate"
output = p.communicate()[0]
print "py: after p.communicate"
print "py: returncode=",p.returncode
print "py: read",len(output),"bytes"
print "py: output=", repr(output)
print "py: End of foo.py"
gabriel at sleipnir:~$ ./foo.py
py: before p.communicate
py: after p.communicate
py: returncode= 0
py: read 143 bytes
py: output= 'End of foo.sh\n5 seconds remaining...\n4 seconds
remaining...\n3 seconds remaining...\n2 seconds remaining...\n1 seconds
remaining...\nEnd of foo.pl\n'
py: End of foo.py
gabriel at sleipnir:~$ uname -a
Linux debian 2.6.18-4-486 #1 Mon Mar 26 16:39:10 UTC 2007 i686 GNU/Linux
gabriel at sleipnir:~$
</log>
This was tested both with python 2.4.4 and 2.5.2
I don't think it's a Python problem, but something related to java and how
it handles stdin/stdout. Try with another program.
> But, my question now is, WHY is this an issue? If the launched
> process doesn't read from its stdin, why would it block?
Several reasons - the child process might send enough text to stderr to
fill its buffer, and if the parent process doesn't read from the other end
of the pipe, the child blocks. That's why I suggested to use communicate
instead of stdout.read() - it takes care of such cases.
> The only thing I can think of is that the JVM's stdout is tied to the
> shell script's stdout, because that's the only way it can remain open
> upon the termination of the child process. I suppose, at this point,
> the next place to look is in shell script syntax to find out how to
> detach the JVM from the script's process group.
Can't you redirect to a file instead?
java foo.jar >/tmp/foo.log 2>&1 &
--
Gabriel Genellina
More information about the Python-list
mailing list