How do you display stdout on a web page generated by Python?

Go To StackoverFlow.com

2

I am writing a web application that will execute a command on the local Windows server and need to display the output. The Popen() call in my code executes fine on the Python interpreter but gives a nasty error when executed via IIS. Thanks!!!!

Error text:

Traceback (most recent call last):

File "C:\pythonapps\mystdout.py", line 9, in print Popen('ipconfig', shell=True, stdout=PIPE).communicate()[0]

File "C:\Python27\lib\subprocess.py", line 672, in init errread, errwrite) = self._get_handles(stdin, stdout, stderr)

File "C:\Python27\lib\subprocess.py", line 774, in _get_handles p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE)

WindowsError: [Error 6] The handle is invalid

from subprocess import *

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>FSPCT app</title>"
print "</head>"
print "<body>"
print Popen('ipconfig', shell=True, stdout=PIPE).communicate()[0]
print "</body>"
print "</html>"
2012-04-05 20:46
by bradtaco


2

It looks like the IIS server doesn't have a valid stdin file handle (not all that surprising, as it's a server process). The subprocess module is trying to copy that stdin file handle... and failing.

To fix this, call Popen for the subprocess you're executing with the stdin file handle (and maybe stderr too for good measure) bound to the NUL file. (os.devnull is the portable way of referring to that file in Python 2.7.) Said NUL file (or /dev/null under Unix) simply discards everything written to it, and returns end-of-file immediately when read from. Perfect for this.

Try modifying your code like this:

import os
...
with open(os.devnull, 'r+') as nul:
    print Popen('ipconfig', shell=True, stdin=nul, stdout=PIPE, stderr=nul).communicate()[0]

(In the upcoming Python 3.3, you can now pass subprocess.DEVNULL to the stdin, stdout or stderr arguments of Popen to do the same thing more concisely.)

2012-04-05 21:18
by Christian Hudon
a bit of a waste to open /dev/null when subprocess will have the same effect when you communicate() or communicate('') after specifying stdin=PIPElunixbochs 2012-04-05 21:33
Thanks Christian. That worked for me - bradtaco 2012-04-06 17:15
@lunixbochs A bit longer to type, maybe. But not anymore of a waste than using stdin=PIPE, which also opens a file descriptor object, although behind the scenes. It's also a bit more robust to pass /dev/null than a pipe, if your program won't be attending to said pipe. For example, if the subprocess you're spawning (unexpectedly) tries to read from stdin, with /dev/null it will get an EOF immediately. But with a pipe, it will hang there waiting for input from said pipe, which will never come - Christian Hudon 2012-04-09 16:32
communicate() has the exact same behavior: Popen('cat', shell=True, stdin=PIPE, stdout=PIPE).communicate()[0] (on a system with cat present) will exit immediately, exactly as if you had passed /dev/null to stdin. As such, opening and passing devnull serves no real purpose but complicating the code - lunixbochs 2012-04-09 18:40
It serves the purpose of making it clear what the intent of the programmer was (no communication coming from stdin, output of stderr ignored), for one extra line of code (zero in Python 3.3+). I guess we'll have to agree to disagree - Christian Hudon 2012-04-10 17:01


2

The default subprocess.Popen() value for stdin is None, which passes stdin from the parent process.

To use an internal stdin, just pass stdin=PIPE with your Popen() call.

print Popen('ipconfig', shell=True, stdin=PIPE, stdout=PIPE).communicate()[0]
2012-04-05 21:29
by lunixbochs
Ads