簡體   English   中英

Python:將sys.stdout和sys.stderr都捕獲為日志文件

[英]Python: capturing both of sys.stdout and sys.stderr as a log file

粗略地說,我想將此移植到純Python:

#!/bin/bash

{
    python test.py
} &> /tmp/test.log

由於某些未知原因,此方法不起作用:

import os.path, sys
import tempfile

with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
    sys.stdout = sys.stderr = fp
    raise Exception("I'm dying")

當我在CentOS x86_64上使用Python 2.6.6,Python 2.7.8和Python 3.4.2對其進行測試時,生成的test.log為空(並且我在控制台上看不到任何內容)。

但理想情況下,我想要Python 2.6的解決方案。

(目前,只要任何數據都不會簡單地消失在黑洞中,就可以容忍日志文件與stdoutstderr或多線程的混合輸出雜亂無章。)

請向我展示一個簡潔且可移植的解決方案,該解決方案可以在sys.stderr上的異常堆棧跟蹤中使用。 (最好是os.dup2以外的os.dup2

您可以使用如下方法:

import traceback
import sys
from contextlib import contextmanager


@contextmanager
def output_to_file(filepath, write_mode='w'):
    stdout_orig = None
    stderr_orig = None

    stdout_orig = sys.stdout
    stderr_orig = sys.stderr

    f = open(filepath, write_mode)

    sys.stdout = f
    sys.stderr = f

    try:
        yield
    except:
        info = sys.exc_info()
        f.write('\n'.join(traceback.format_exception(*info)))

    f.close()

    sys.stdout = stdout_orig
    sys.stderr = stderr_orig

用法是:

with output_to_file('test.log'):
    print('hello')
    raise Exception('I am dying')

cat test.log產生:

hello
Traceback (most recent call last):

  File "<ipython-input-3-a3b702c7b741>", line 20, in outputi_to_file
    yield

  File "<ipython-input-4-f879d82580b2>", line 3, in <module>
    raise Exception('I am dying')

Exception: I am dying

請記住,文件對象在with塊之后關閉:)

簡單地使用這個:

sys.stdout = sys.stderr = open("test.log","w")
raise Exception("Dead")

退出后test.log的內容:

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    raise Exception("Dead")
Exception: Dead

這對我有用:

#!/usr/bin/env python
from __future__ import print_function
import os, os.path, sys, tempfile

old_out = os.dup(sys.stdout.fileno())
old_err = os.dup(sys.stderr.fileno())
with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
    fd = fp.fileno()
    os.dup2(fd, sys.stdout.fileno())
    os.dup2(fd, sys.stderr.fileno())
    print("Testing")
    print('testing errs', file=sys.stderr)
    raise Exception("I'm dying")

未來只是為了更干凈地處理具有相同示例的Python2或Python3。 (我還更改了raise語句以實例化異常,字符串已被棄用很長時間了,而Python3則不正確支持這些字符串)。

old_ *值僅表示我們要在使用重定向文件后恢復原始的stdout和/或stderr。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM