Как перенаправить stderr в Python?

Я хотел бы зарегистрировать весь вывод сценария Python. Я попробовал:

import sys

log = []

class writer(object):
    def write(self, data):
        log.append(data)

sys.stdout = writer()
sys.stderr = writer()

Теперь, если я "печатаю 'что-то'", это зарегистрировано. Но если я сделаю, например, некоторую синтаксическую ошибку, скажу "печать 'something#", это, привычка зарегистрирована - она войдет в консоль вместо этого.

Как я фиксирую также ошибки от интерпретатора Python?

Я видел возможное решение здесь:

http://www.velocityreviews.com/forums/showpost.php?p=1868822&postcount=3

но второй пример входит в/dev/null - это не то, что я хочу. Я хотел бы зарегистрировать его в список как мой пример выше или StringIO или такой...

Кроме того, предпочтительно я не хочу создавать подпроцесс (и читать его stdout и stderr в отдельном потоке).

19
задан EcirH 24 December 2009 в 00:46
поделиться

3 ответа

Вы не можете делать в коде Python ничего, что могло бы фиксировать ошибки во время компиляции того же самого кода. Как это могло быть? Если компилятор не может завершить компиляцию кода, он не будет запускать код, поэтому ваше перенаправление еще даже не вступило в силу.

Вот где вступает ваш (нежелательный) подпроцесс. Вы можете написать код Python, который перенаправляет stdout, затем вызывает интерпретатор Python для компиляции другого фрагмента кода.

6
ответ дан 30 November 2019 в 03:29
поделиться

Я не могу придумать легкого пути. Стандартная ошибка процесса python находится на более низком уровне, чем объект файла python (C против python).

Вы можете обернуть сценарий python во второй сценарий python и использовать subprocess.Popen. Также возможно, что вы могли бы использовать такую ​​магию в одном скрипте:

import os
import subprocess
import sys

cat = subprocess.Popen("/bin/cat", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
os.close(sys.stderr.fileno())
os.dup2(cat.stdin.fileno(), sys.stderr.fileno())

А затем использовать select.poll (), чтобы регулярно проверять cat.stdout на предмет вывода.

Да, похоже, это работает.

Проблема, которую я предвижу, заключается в том, что в большинстве случаев что-то, напечатанное в stderr с помощью python, указывает на то, что он вот-вот завершится. Более обычный способ справиться с этим - использовать исключения.

--------- Edit

Как-то я пропустил функцию os.pipe ().

import os, sys
r, w = os.pipe()
os.close(sys.stderr.fileno())
os.dup2(w, sys.stderr.fileno())

Затем прочтите из r

6
ответ дан 30 November 2019 в 03:29
поделиться

У меня есть программа, которую я написал для работы, которая записывает stderr в такой файл:

import sys
sys.stderr = open('C:\\err.txt', 'w')

, так что это определенно возможно.

Я считаю, что ваша проблема в том, что вы создаете два экземпляры писателя.

Может быть, что-то более похожее:

import sys

class writer(object):
    log = []

    def write(self, data):
        self.log.append(data)

logger = writer()
sys.stdout = logger
sys.stderr = logger
20
ответ дан 30 November 2019 в 03:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: