2010-10-13 216 views
2

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

我们通过查看输出文件是否实际创建(无论如何总是返回0)来检查它是否失败。但是,如果子进程失败,则表明没有任何内容打印到stderr或stdout。 (它成功地处理了大约100个左右,但只有一个单独的一个很糟糕,但我希望能够看到是什么原因导致错误)

小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 

EDIT 2

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

+0

当你用'2> out.err'从cmd运行它时会发生什么? out.err是否以文本结束? – 2010-10-13 18:51:57

+0

是的,它正确打印出消息。 – UberJumper 2010-10-13 18:52:46

+0

可以肯定的是,“打印出来”的意思是“把它放在文件中”,对吧?它不显示在屏幕上。 – 2010-10-13 18:57:52

回答

5

由于错误消息真的不来了在任一stdout也不stderr,我最好的猜测是,该程序正在使用Windows的等效断开/dev/tty的,不管它是什么。在Unix中,你可以小心使用pty.openpty来拦截,但据我所知,在Python中不支持类似的Windows特定技巧。您可以尝试使用Expect for Windows

+0

我和Zack在一起。 Windows可执行文件可以执行几项*看起来像写入到stdio,但不是真的。对于Windows而言,期望有助于帮助(即在某些情况下),但并非总是如此(从这个意义上来说,Expect-for-Windows不是通用的)。 – 2010-10-13 19:02:17

+0

有一点要尝试的是获得一个Windows API间谍,看看你是否可以挑选出它在做什么。像http://www.apimonitor.com/ – 2010-10-13 19:54:14

+0

看起来很好看,它不是我所希望的。我想我只是不得不放手。原来ERDAS将所有stdout/stderr重定向到它们的日志子系统。这个日志子系统然后将输出重定向到“CON”,我不认为有一种方法来捕获这个输出,所以我想我几乎在这里输了。 – UberJumper 2010-10-13 19:54:58

0

你使用python 2.5还是2.6的早期版本? 你可以试试这个子过程。与标准错误重定向check_output到stdout:

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

如果out_err得到两个输出和错误,你可能需要重定向输出和错误到文件的对象,后来从这些文件中的对象读取(因为Windows不具备UNIX如下:

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