Win XP: Problem with shell scripting in Python

John Machin sjmachin at lexicon.net
Fri Jun 9 18:01:04 EDT 2006


On 10/06/2006 3:00 AM, A.M wrote:
> Here is what I came up with after John and Fredrik's help.
> 
> import os
> import sys
> def Execute(shell_command,logStream = sys.stdout):
>     print >>logStream, shell_command
>     child_stdin, child_stdout_and_stderr  = os.popen4(shell_command)
>     commad_output = child_stdout_and_stderr.read()
>     print >>logStream,  commad_output
>     return_code = child_stdout_and_stderr.close()
>     return_code = return_code or child_stdin.close()
>     print  >>logStream, "Return Code: " , return_code
> 
> Execute ("DIR")
> 
> Execute ("MD :")
> 
> I tested it and so far it behaves the way that I want.
> 

Does it overcome the problem that you reported earlier, that the 
contents of the output file from BCP were out of order? If not, you may 
like to try popen3(). It's quite possible (and indeed desirable) that 
the child's stderr is not buffered (so that error messages appear 
immediately) but the child's stdout is buffered (for efficiency), and 
when the buffer is flushed governs the order of appearance in a single 
output stream.
> 
> 
> The tricky part is that when you use popen4, you have to close both returned 
> streams to be able to get the return code. I wasn't able to find that in the 
> documentation.

In general it is good practice to hand back resources (e.g. close files) 
explicitly as soon as you are finished with them. This is especially 
important for files open for writing, in case there are problems like 
out of disk space, device not functioning etc. Also when you are dealing 
with a child process it makes some sense to close its stdin first just 
in case it is waiting for that, and will then write something to stdout, 
which may fail, causing it to write to stderr. So I guess that the 
documenter didn't stumble onto the "tricky part" :-)

The "tricky part" for popen and friends seems to be that the return code 
is handed back upon close of the *last* file:

|>>> h = os.popen3('md : ')
|>>> [h[x].close() for x in 2, 1, 0]
[None, None, 1]

Looks like you get to report a documentation "problem" after all :-)

Cheers,
John





More information about the Python-list mailing list