Изменение: поскольку кажется, что нет ни одного решения, либо я делаю что-то настолько нестандартное, что никто не знает - я пересмотрю свой вопрос, чтобы спросить: что является лучшим способом для ведения журнала, когда приложение python создает много системных вызовов?
Мое приложение имеет два режима. В интерактивном режиме я хочу, чтобы все выходные данные поступали на экран, а также в файл журнала, включая вывод любых системных вызовов. В режиме демона все выходные данные поступают в журнал. Режим Daemon отлично работает с помощью os.dup2()
. Я не могу найти способ "вытащить" весь вывод в журнал в интерактивном режиме, не изменяя каждый системный вызов.
Другими словами, я хочу, чтобы функциональность командной строки "tee" для любого выхода, созданного приложением python, включая выход системного вызова.
Чтобы уточнить:
Чтобы перенаправить все выходные, я делаю что-то вроде этого, и он отлично работает:
# open our log file
so = se = open("%s.log" % self.name, 'w', 0)
# re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
Самое приятное в этом состоит в том, что он не требует специальных вызовов печати от остальной части кода. В коде также выполняются некоторые команды оболочки, поэтому неплохо не иметь дело с каждым их выходом отдельно.
Просто я хочу сделать то же самое, кроме дублирования вместо перенаправления.
Сперва подумал, я подумал, что нужно просто перевернуть dup2
. Почему не так? Здесь мой тест:
import os, sys
### my broken solution:
so = se = open("a.log", 'w', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
os.dup2(sys.stdout.fileno(), so.fileno())
os.dup2(sys.stderr.fileno(), se.fileno())
###
print("foo bar")
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
Файл "a.log" должен быть идентичен тому, что отображалось на экране.