【问题标题】:Capturing Console output that is not written to stdout,stderr?捕获未写入 stdout、stderr 的控制台输出?
【发布时间】:2011-04-25 00:37:43
【问题描述】:

我有一个名为 pregeocode 的 Windows 应用程序(我们缺少源代码),该程序基本上将地理编码写入输入文件。除非出现错误,否则该程序实际上不会向控制台写入任何内容。该程序通常从一个小型 Python 程序中调用(它处理参数等,并进行所有有趣的预处理)。

我们通过查看输出文件是否实际创建来检查它是否失败(无论如何它总是返回 0)。但是,当它失败时,子进程显示没有任何内容打印到 stderr 或 stdout。 (它成功处理了大约一百个左右,通常只有一个是坏的,但我希望能够看到导致错误的原因)

小python脚本通过subprocess.Popen调用应用程序:

argslist = [r'C:\workspace\apps\pregeocode.exe', '-in', inputfilename, '-out', outputfilename, '-gcp', gcp_file]
p = subprocess.Popen(argslist, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
print str(p.communicate())

给出以下输出:

('', '')

但是,如果我通过 cmd 使用相同的参数手动运行程序,我会得到以下输出:

45 IMAGE_EXTENT_TOO_SMALL

(大约有 60 条不同的错误信息,45 表示错误号)

使用 shell=True 参数不会改变任何东西,我也无法在网上找到任何关于此问题的信息。实际的 exe 是很久以前在内部制作的,我们缺少它的源代码,所以我看不到它是如何打印出消息的。

那么为什么 subprocess 不能实际捕获这个的 stdout 或 stderr 呢?

编辑

os.system(" ".join(argslist))

正确打印错误信息:

45 IMAGE_EXTENT_TOO_SMALL

编辑 2

原来应用程序使用 ERDAS 的工具包。他们的工具包将所有标准输出/标准错误重定向到他们的日志子系统。日志子系统然后通过“CON”重写它。

【问题讨论】:

  • 当您使用2> out.err 从cmd 运行它时会发生什么? out.err 是否以文本结尾?
  • 是的,它正确地打印出消息。
  • 可以肯定的是,“打印输出”的意思是“放入文件中”,对吧?它不会显示在屏幕上。
  • 它将它打印到控制台但不将输出重定向到文件。抱歉,请快速添加评论。所以 out.err 文件完全是空的。
  • 那时可能没有使用stderr。我认为@zack 正在做某事。

标签: python subprocess


【解决方案1】:

由于错误消息确实没有出现在stdoutstderr 上,我最好的猜测是该程序正在使用Windows 相当于打开/dev/tty,不管是什么。在 Unix 中,您可以通过仔细使用 pty.openpty 来拦截它,但据我所知,Python 中不支持类似的 Windows 特定技巧。你可以试试Expect for Windows

【讨论】:

  • 我和扎克在一起。 Windows 可执行文件可以做几件看起来类似于写入标准输入输出的事情,但实际上并非如此。 Expect-for-Windows 有时会有所帮助(也就是说,在某些情况下),但并非总是如此(从这个意义上说,Expect-for-Windows 并不是通用的)。
  • 要尝试的一件事是获取Windows API spy,看看您是否可以找出它在做什么。类似apimonitor.com
  • 看了一下,它不是我所希望的。我想我将不得不放手。结果 ERDAS 将所有标准输出/标准错误重定向到他们的日志子系统。然后这个日志子系统将输出重定向到“CON”,我认为没有办法捕获这个输出,所以我想我在这里几乎不知所措。
  • 我整天都在解决这个确切的问题:试图在 Windows 中捕获 CON。我不认为它可以做到。 stackoverflow.com/questions/49594237/…
【解决方案2】:

您使用的是 python 2.5 还是 2.6 的早期版本? 你可以试试这个 subprocess.check_output 与 stderr 重定向到 stdout:

out_err = subprocess.check_output(argslist, stderr=subprocess.STDOUT)

如果 out_err 得到输出和错误,您可能需要将 stdout 和 stderr 重定向到文件对象,然后从这些文件对象中读取(因为 windows 没有类似 unix 的管道):

fout = open('fout', 'w')
ferr = open('ferr', 'w')    
p = subprocess.Popen(argslist, stdout=fout, stderr=ferr)
p.wait()
fout.close()
ferr.close()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多