2010-10-13 4 views
2

У меня есть приложение Windows, называемое pregeocode (у нас нет источника), эта программа в основном записывает геокодирование во входной файл. Эта программа на самом деле ничего не пишет на консоль, если есть ошибка. Эта программа, как правило, вызывается из небольшой программы Python (она обрабатывает аргументы и т. Д. И делает все, что нужно для предварительной обработки).Захват вывода консоли, который не записывается в stdout, stderr?

Мы проверяем, не сработало ли оно, посмотрев, действительно ли был создан выходной файл (он всегда возвращает 0, несмотря ни на что). Однако, когда он не работает, подпроцесс показывает, что ничего не было напечатано в stderr или stdout. (Он обрабатывает около ста или так успешно, с usasally только один из них плохой, но мне бы хотелось увидеть, что вызывает ошибку)

Маленький скрипт python вызывает приложение через подпроцесс.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()) 

дает выход:

('', '') 

Однако, если я запустить программу вручную, используя те же аргументы через ЦМД, я получаю выход:

45 IMAGE_EXTENT_TOO_SMALL 

(Существует около 60 различных нечетных сообщений об ошибках, 45 указывает номер ошибки)

Использование оболочки = True аргумент ничего не изменится, и я не могу ничего найти в Интернете об этой проблеме. Фактический exe - это то, что было сделано в доме давным-давно, и нам не хватает исходного кода, поэтому я не вижу, как он печатает сообщения.

Так почему же подпроцесс не может фактически захватить stdout или stderr этого?

EDIT

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

правильно печатает сообщение об ошибке:

45 IMAGE_EXTENT_TOO_SMALL 

EDIT 2

Оказывается, приложение использует инструментарий ERDAS в. Их инструментарий перенаправляет все stdout/stderr в свою подсистему регистрации. Подсистема протоколирования затем перезаписывает ее через «CON».

+0

Что происходит, когда вы запускаете его из cmd с '2> out.err'? Выводит ли out.err текст? –

+0

Yup правильно распечатывает сообщение. – UberJumper

+0

Чтобы быть уверенным, «распечатать» означает «помещает его в файл», правильно? Он не отображается на экране. –

ответ

5

Поскольку сообщение об ошибке на самом деле не приходит в обеих stdout ни stderr, моя догадка, что программа использует эквивалент Windows' открытия /dev/tty, что бы это ни. В Unix вы можете перехватить это с осторожным использованием pty.openpty, но, насколько я знаю, в Python нет поддержки подобных трюков для Windows. Вместо этого вы можете попробовать Expect for Windows.

+0

Я с Заком. Исполняемые файлы Windows могут делать несколько вещей, которые * выглядят *, как запись в stdio, но на самом деле это не так. Иногда Expect-for-Windows помогает (то есть в некоторых из этих случаев), но не всегда (Expect-for-Windows не является универсальным, в этом смысле). –

+0

Одна вещь, чтобы попытаться получить шпион Windows API, чтобы увидеть, можете ли вы выбрать, что он делает. Что-то вроде http://www.apimonitor.com/ –

+0

Взял хороший взгляд, на самом деле это не то, на что я надеялся. Наверное, мне просто придется это отпустить. Выключает ERDAS перенаправляет все stdout/stderr в свою подсистему ведения журнала. Эта подсистема регистрации затем имеет выход, перенаправленный на «CON», я не думаю, что есть способ захватить этот вывод, поэтому, я думаю, я в значительной степени теряю здесь. – UberJumper

0

Вы используете python 2.5 или раннюю версию 2.6? Можете ли вы попробовать этот подпроцесс.check_output с Stderr перенаправления на стандартный вывод:

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

Если out_err получает как выход и ошибок, вам, вероятно, нужно перенаправить стандартный вывод и стандартный поток ошибок в файл объектов, а затем считываются из этих файловых объектов (потому что окна не имеют UNIX -подобные трубы):

fout = open('fout', 'w') 
ferr = open('ferr', 'w')  
p = subprocess.Popen(argslist, stdout=fout, stderr=ferr) 
p.wait() 
fout.close() 
ferr.close() 
Смежные вопросы