Python – захватить весь вывод из вызова функции, выполняющей внешнюю программу

Я запускаю интеграционные тесты с Nose. В одном из моих тестов мне нужно получить вывод и проанализировать его, чтобы найти определенную строку.

def test_diagnostic_tool():
    with Capturing() as output:
        failures = run_integration_testing_exe('*', test_exe='DiagnosticTool.exe', use_default_composed_filter=False)

    eq_(failures, 0)


class Capturing(list):
    def __enter__(self):
        self._stdout = sys.stdout
        sys.stdout = self._stringio = StringIO()
        return self

    def __exit__(self, *args):
        self.extend(self._stringio.getvalue().splitlines())
        sys.stdout = self._stdout

Это не работает. Переменная «output» содержит только небольшую строку из печати где-то в структуре вызова.

Функция run_integration_testing_exe вызывает другую функцию, и там вызывается внешняя программа exe. В оболочке все выводится нормально, поэтому мне было интересно, есть ли способ захватить все это и проанализировать.


person Amaranth    schedule 15.07.2014    source источник
comment
Вероятно, вам нужно включить код функции, которая фактически запускает внешнюю программу, поскольку это зависит от того, как, например. subprocess.Popen вызывается, если это то, что запускает exe.   -  person deinonychusaur    schedule 15.07.2014
comment
Я бы хотел. Эта функция является частью среды тестирования, и я не могу ее изменить (я импортирую ее в свой тестовый скрипт).   -  person Amaranth    schedule 15.07.2014
comment
Вы уверены, что то, что вам не хватает, на самом деле было написано на стандартный вывод, а не на стандартный вывод? В противном случае, если вы не можете добраться до кода, который запускает DiagnosticTool.exe, вам, вероятно, не повезло изнутри python.   -  person deinonychusaur    schedule 15.07.2014
comment
Я не пользователь Windows, но это может быть связано с stackoverflow.com/questions/3018848/, может быть?   -  person deinonychusaur    schedule 15.07.2014
comment
nose имеет аргумент командной строки --no-capture, который сохраняет stdout в тестовых фикстурах, что позволит вам захватить/разобрать stdout вашего нового процесса.   -  person blakev    schedule 15.07.2014


Ответы (1)


Вы можете попробовать перенаправить из sys.__stdout__ в свой класс Capturing, просто чтобы исключить возможность того, что нос или другие плагины в носу будут мешать вам захватывать вывод. Этот объект содержит исходные значения stdout в начале программы, как описано в sys docs. . Это будет работать только в том случае, если ваш исполняемый процесс уже правильно перенаправил свой поток stdout в поток интерпретатора Python.

Но думаю особой разницы не будет. Ключевым моментом здесь является то, что захват и перенаправление sys.stdout в большинстве случаев не влияет на стандартные потоки ввода-вывода процессов, выполняемых семейством функций subprocess(), что, я полагаю, происходит здесь.

Лучше всего явно захватить стандартный вывод из вашего вызова subprocess.Popen, используя subprocess.PIPE и communicate() (например, здесь), распечатайте его в тесте и дайте носу захватить. Существует большая вероятность того, что вызов subprocess выполняется через оболочку и находится за пределами стандартного вывода, над которым python имеет контроль.

И если вы не можете изменить этот код, вы всегда можете его пропатчить ;-)

person Oleksiy    schedule 16.07.2014
comment
Я пробовал, но не получилось. Я не знаю, что именно вы имеете в виду под обезьяньим путем. Тем не менее, я смог связаться с людьми, отвечающими за этот плагин, и попросил их захватить и вернуть вывод с помощью функции. - person Amaranth; 02.08.2014
comment
Я имел в виду динамическое изменение кода плагина на что-то еще, что на самом деле захватывает STDOUT, но похоже, что у вас есть возможность сделать это правильно. - person Oleksiy; 02.08.2014