【问题标题】:How do you display stdout on a web page generated by Python?如何在 Python 生成的网页上显示标准输出?
【发布时间】:2012-04-19 14:46:29
【问题描述】:

我正在编写一个 Web 应用程序,它将在本地 Windows 服务器上执行命令并需要显示输出。我代码中的 Popen() 调用在 Python 解释器上执行良好,但在通过 IIS 执行时会出现严重错误。谢谢!!!!

错误文本:

Traceback(最近一次调用最后一次):

文件“C:\pythonapps\mystdout.py”,第 9 行,打印 Popen('ipconfig', shell=True, stdout=PIPE).communicate()[0]

文件“C:\Python27\lib\subprocess.py”,第 672 行,在 init 中出错, errwrite) = self._get_handles(stdin, stdout, stderr)

文件“C:\Python27\lib\subprocess.py”,第 774 行,在 _get_handles 中 p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE)

WindowsError: [错误 6] 句柄无效

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>"

【问题讨论】:

    标签: python python-2.7 iis-7


    【解决方案1】:

    看起来 IIS 服务器没有有效的标准输入文件句柄(这并不奇怪,因为它是一个服务器进程)。 subprocess 模块正在尝试复制该标准输入文件句柄......但失败了。

    要解决此问题,请为您正在执行的子进程调用Popen,并将标准输入文件句柄(也可能是标准错误)绑定到 NUL 文件。 (os.devnull 是 Python 2.7 中引用该文件的可移植方式。)所述 NUL 文件(或 Unix 下的 /dev/null)只是丢弃写入它的所有内容,并在读取时立即返回文件结尾。非常适合这个。

    尝试像这样修改您的代码:

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

    (在即将发布的 Python 3.3 中,您现在可以将 subprocess.DEVNULL 传递给 Popen 的 stdin、stdout 或 stderr 参数以更简洁地执行相同的操作。)

    【讨论】:

    • subprocess时打开/dev/null有点浪费当你在指定stdin=PIPEcommunicate()communicate('')时会产生同样的效果
    • @lunixbochs 可能打字时间长一点。但没有比使用 stdin=PIPE 更浪费了,它也打开了一个文件描述符对象,虽然在幕后。如果您的程序不关注所述管道,则传递 /dev/null 也比管道更健壮。例如,如果您正在生成的子进程(意外)尝试从标准输入读取,使用 /dev/null 它将立即获得 EOF。但是对于管道,它会挂在那里等待来自所述管道的输入,而这永远不会到来。
    • communicate() 具有完全相同的行为:Popen('cat', shell=True, stdin=PIPE, stdout=PIPE).communicate()[0](在存在cat 的系统上)将立即退出,就像您将/dev/null 传递给标准输入一样。因此,打开和传递 devnull 没有任何实际用途,只会使代码复杂化。
    • 它的目的是明确程序员的意图是什么(没有来自标准输入的通信,忽略标准错误的输出),用于多行代码(Python 3.3+ 中为零)。我想我们必须同意不同意。
    【解决方案2】:

    标准输入的默认subprocess.Popen() 值为None,它从父进程传递标准输入。

    要使用内部标准输入,只需通过 Popen() 调用传递 stdin=PIPE

    print Popen('ipconfig', shell=True, stdin=PIPE, stdout=PIPE).communicate()[0]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-06
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      相关资源
      最近更新 更多