Grokbase Groups Python tutor May 2005
FAQ

---------- Forwarded message ----------
Date: Thu, 12 May 2005 11:31:57 -0600
From: Jeffrey Rice <jeffrice at finity.org>
To: Danny Yoo <dyoo at hkn.eecs.berkeley.edu>
Subject: Re: [Tutor] Pipe variable to external command


At 12:16 AM 5/12/2005, Danny Yoo wrote:
######
child_out, child_in = popen2.popen2("wc")
child_in.write("hello world\nthis is a test\ngoodbye!\n")
child_in.close()
result = child_out.read()
child_out.close()
result
' 3 7 36\n'
######
Thanks for your help -- this is working, with a minor wrinkle I have not
cleared up yet. I also need to read stderr, so I looked at the docs and it
seems that popen2.popen3 is the tool.

* * * *
CLAMAV_out, CLAMAV_in, CLAMAV_err= popen2.popen3(CLAMAV)
CLAMAV_in.write(WORKING)
CLAMAV_in.close()
CLAM_RESULT=CLAMAV_out.read()
CLAMAV_out.close()
CLAM_ERR=CLAMAV_err.read()
CLAMAV_err.close()
* * * *

CLAM_RESULT gives the correct reply, and stderr is 1. But CLAM_ERR is
empty. This seems like it should be simple -- what am I missing?

Jeff



* * * * * * *
Jeffrey Rice || jeffrice at finity.org || www.finity.org

Search Discussions

  • Jeffrey Rice at May 12, 2005 at 6:17 pm

    At 11:56 AM 5/12/2005, Danny Yoo wrote:
    * * * *
    CLAMAV_out, CLAMAV_in, CLAMAV_err= popen2.popen3(CLAMAV)
    CLAMAV_in.write(WORKING)
    CLAMAV_in.close()
    CLAM_RESULT=CLAMAV_out.read()
    CLAMAV_out.close()
    CLAM_ERR=CLAMAV_err.read()
    CLAMAV_err.close()
    * * * *

    CLAM_RESULT gives the correct reply, and stderr is 1. But CLAM_ERR is
    empty. This seems like it should be simple -- what am I missing?
    I think I am messing this up! What I actually need is the exitcode of the
    spawned command, which is why stderr did not contain the info I wanted. It
    seems there is a new problem: to get the exitcode of the spawned process,
    not the "shell" that contains it. I found this example on another list
    that seems to address this problem:

    http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/68786
    As a work around, I end up calling popen3 like this:

    Open3.popen3 ("/some/command/to/run ; echo $? 1>&2") { ... }

    That ensures the exit code from /some/command/to/run will be the last
    line of the standard error stream from Open3.popen3. Then I can just
    pull that line off the output to get the return code.


    Is there a more elegant way to get the exitcode off the child process, or
    is this the "approved" method?

    Jeff

    * * * * * * *
    Jeffrey Rice || jeffrice at finity.org || www.finity.org
  • Danny Yoo at May 12, 2005 at 6:24 pm

    http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/68786
    As a work around, I end up calling popen3 like this:

    Open3.popen3 ("/some/command/to/run ; echo $? 1>&2") { ... }

    That ensures the exit code from /some/command/to/run will be the last
    line of the standard error stream from Open3.popen3. Then I can just
    pull that line off the output to get the return code.

    Hi Jeffrey,

    Ah! Ok, you're looking for the error code too.


    Is there a more elegant way to get the exitcode off the child process,
    or is this the "approved" method?
    Yeah; check the Popen3 object in the 'popen2' module: it has a separate
    way of getting at the error code:

    http://www.python.org/doc/lib/popen3-objects.html


    For example:

    ######
    import popen2
    process = popen2.Popen3(['wc'])
    process.tochild.write("hello\nworld")
    process.tochild.close()
    process.fromchild.read()
    ' 1 2 11\n'
    process.fromchild.close()
    process.wait()
    ######


    Hope this helps!
  • Jeffrey Rice at May 12, 2005 at 9:22 pm

    At 12:24 PM 5/12/2005, Danny Yoo wrote:
    ######
    import popen2
    process = popen2.Popen3(['wc'])
    process.tochild.write("hello\nworld")
    process.tochild.close()
    process.fromchild.read()
    ' 1 2 11\n'
    process.fromchild.close()
    process.wait()
    ######
    This is all well and good if the child exits with 0, but things get a
    little funky if it doesn't.

    For example, modifying the model to have clamdscan exit with 0:

    ######
    import popen2
    process = popen2.Popen3(['clamdscan','ham.test'])
    process.tochild.close()
    process.fromchild.read()
    'ham.test: OK\n\n----------- SCAN SUMMARY -----------\nInfected files:
    0\nTime: 0.098 sec (0 m 0 s)\n'
    process.fromchild.close()
    process.wait()
    ######

    Now rewrite it to return an exit code of 1:

    ######
    import popen2
    process = popen2.Popen3(['clamdscan','eicar.test'])
    process.tochild.write("hello\nworld")
    process.tochild.close()
    process.fromchild.read()
    'eicar.test: Eicar-Test-Signature FOUND\n\n----------- SCAN SUMMARY
    -----------\nInfected files: 1\nTime: 0.043 sec (0 m 0 s)\n'
    process.fromchild.close()
    process.wait()
    256
    ######

    Now for a exit code of 2:

    ######
    import popen2
    process = popen2.Popen3(['clamdscan','nonexistent.test'])
    process.tochild.close()
    process.fromchild.read()
    '\n----------- SCAN SUMMARY -----------\nInfected files: 0\nTime: 0.004 sec
    (0 m 0 s)\n'
    process.fromchild.close()
    process.wait()
    512
    ######

    In my fiirst example, clamdscan should return 1 when the EICAR string is
    found -- process.wait() gets 256 instead.
    In the second, clamdscan returns 2 if an error occurs, such as trying to
    scan a non-existent file, but 512 is returned.

    No doubt there is a reason why the exit code is getting multiplied by
    256... ??? My search has not enlightened me, however.

    Jeff


    * * * * * * *
    Jeffrey Rice || jeffrice at finity.org || www.finity.org
  • Danny Yoo at May 12, 2005 at 11:10 pm

    In my first example, clamdscan should return 1 when the EICAR string is
    found -- process.wait() gets 256 instead. In the second, clamdscan
    returns 2 if an error occurs, such as trying to scan a non-existent
    file, but 512 is returned.

    No doubt there is a reason why the exit code is getting multiplied by
    256... ??? My search has not enlightened me, however.

    The return value of wait() packs a few values in a single integer, so you
    may need to do some bit manipulation. The popen2 documentation talks
    about this:

    """
    wait()
    Waits for and returns the status code of the child process. The status
    code encodes both the return code of the process and information about
    whether it exited using the exit() system call or died due to a signal.
    Functions to help interpret the status code are defined in the os module;
    see section 6.1.5 for the W*() family of functions.
    """

    http://www.python.org/doc/lib/popen3-objects.html


    You can take a look near the bottom of:

    http://www.python.org/doc/lib/os-process.html#os-process

    for functions like os.WEXITSTATUS(), which should help you get the values
    that you're expecting.


    This is all definitely "not obvious" stuff, so please feel free to
    continue to ask questions. Best of wishes!

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouptutor @
categoriespython
postedMay 12, '05 at 5:56p
activeMay 12, '05 at 11:10p
posts5
users2
websitepython.org

2 users in discussion

Danny Yoo: 3 posts Jeffrey Rice: 2 posts

People

Translate

site design / logo © 2022 Grokbase