[Tutor] execute an OS command, get the output

Alan Gauld alan.gauld at freenet.co.uk
Sun Mar 12 12:38:09 CET 2006


Wes,

I haven't tried this but I notice you don't specify shell=True in your Popen 
calls,
that might be the cause - ypou aren't acting like the shell does.

But aws I say thats just a guess based on a quick scim of your port.

Alan G.

----- Original Message ----- 
From: "w chun" <wescpy at gmail.com>
To: <tutor at python.org>
Sent: Sunday, March 12, 2006 3:37 AM
Subject: Re: [Tutor] execute an OS command, get the output


ok, while we're on the subject, i thought i should ask a question for
once(!).  it's been awhile since i played with pipes, and i ran into
this problem on the same day as this post!

if i'm in the shell and playing with a 2-way game with the 'tr' command like 
so:

$ tr '[a-z]' '[A-Z]'
us
US
ca
CA
de
DE
$

i can interactively give the cmd some input via stdin and get
something out of stdout... giving and taking until i press ^D to
terminate the program.

however, when i try this using subprocess/popen2, i find that i can't
do the same interaction, i.e. writing to tr's stdin, reading from tr's
stdout, ad nauseum.  it seems that i have to give tr all of my input,
then close tr's stdin pipe in order to read anything.  (any attempts
at reading before closing results in a blocked OS call, whether it's
using the FD itself or os.read() on its fileno().  the only way for it
to work as i described above is like this:

>>> p = subprocess.Popen(('tr', '"[a-z]"', '"[A-Z]"'),
stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
>>> po, pi = p.stdin, p.stdout
>>> po.write('us\n')
>>> po.write('ca\n')
>>> po.write('de\n')
>>> po.close()
>>> pi.readlines()
['US\n', 'CA\n', 'DE\n']
>>> pi.close()

i was hoping to do somethign more on the lines of:

>>> po.write('us\n')
>>> pi.read() # or pi.readline()
'US\n'
>>> po.write('ca\n')
>>> pi.read()
'CA\n'

but to no avail.  neither sending po.write(chr(4)) nor po.flush() seem
to work.  i basically can tell whether a read() will block (or not)
using select, as in:

>>> from select import select
>>> sel = select([pi], [], [pi], 0)
>>> sel
([], [], []) <--- MEANS IT WILL BLOCK
or
([<open file '<fdopen>', mode 'r' at 0x39ac80>], [], []) -<- WON'T BLOCK

is there anyway to do more "asynchronous" I/O where i can more or less
interact with the other procses rather than what it's doing now?

thanks you guys... i love the tutors!
-wesley




More information about the Tutor mailing list