Как перенаправить stderr в Python?
Я хотел бы записать весь вывод Python script. Я пробовал:
import sys
log = []
class writer(object):
def write(self, data):
log.append(data)
sys.stdout = writer()
sys.stderr = writer()
Теперь, если я "распечатаю" что-то ", он заносится в журнал. Но если я сделаю, например, некоторую синтаксическую ошибку, скажем," напечатайте "что-то #", она не будет регистрироваться - она войдет в консоль вместо этого.
Как я также фиксирую ошибки из интерпретатора Python?
Я видел возможное решение здесь:
http://www.velocityreviews.com/forums/showpost.php?p=1868822&postcount=3
но второй пример записывается в /dev/null - это не то, что я хочу. Я хотел бы записать его в список, например, мой пример выше или StringIO или такой...
Кроме того, предпочтительно, я не хочу создавать подпроцесс (и читать его stdout и stderr в отдельном потоке).
Ответы
Ответ 1
Вы не можете ничего сделать в коде Python, который может захватывать ошибки во время компиляции того же кода. Как это могло быть? Если компилятор не может завершить компиляцию кода, он не будет запускать код, поэтому ваше перенаправление еще не вступила в силу.
То, в которое входит ваш (нежелательный) подпроцесс. Вы можете написать код Python, который перенаправляет stdout, а затем вызывает интерпретатор Python для компиляции другого фрагмента кода.
Ответ 2
У меня есть часть программного обеспечения, которое я написал для работы, которое фиксирует 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
Ответ 3
Я не могу придумать простой способ. Стандартная ошибка процесса python живет на более низком уровне, чем файл файла python (C vs. python).
Вы можете обернуть python script во второй python script и использовать subprocess.Popen. Также возможно, вы могли бы вытащить какую-то магию, как это, в одном script:
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, указывает на ее выход. Более обычный способ справиться с этим будет через исключения.
--------- Редактировать
Как-то я пропустил функцию os.pipe().
import os, sys
r, w = os.pipe()
os.close(sys.stderr.fileno())
os.dup2(w, sys.stderr.fileno())
Затем прочитайте из r
Ответ 4
import sys
import tkinter
# ********************************************
def mklistenconsswitch(*printf: callable) -> callable:
def wrapper(*fcs: callable) -> callable:
def newf(data):
[prf(data) for prf in fcs]
return newf
stdoutw, stderrw = sys.stdout.write, sys.stderr.write
funcs = [(wrapper(sys.stdout.write, *printf), wrapper(sys.stderr.write, *printf)), (stdoutw, stderrw)]
def switch():
sys.stdout.write, sys.stderr.write = dummy = funcs[0]
funcs[0] = funcs[1]
funcs[1] = dummy
return switch
# ********************************************
def datasupplier():
i = 5.5
while i > 0:
yield i
i -= .5
def testloop():
print(supplier.__next__())
svvitch()
root.after(500, testloop)
root = tkinter.Tk()
cons = tkinter.Text(root)
cons.pack(fill='both', expand=True)
supplier = datasupplier()
svvitch = mklistenconsswitch(lambda text: cons.insert('end', text))
testloop()
root.mainloop()
Ответ 5
На самом деле, если вы используете linux/mac os, вы можете просто использовать перенаправление файлов для этого. Например, если вы собираетесь запустить "a.py" и запишите все сообщения, которые будут сгенерированы в файл "a.out", это будет просто
python a.py 2 > & 1 > a.out