如何仅在实际发生错误时将 python 错误 (stderr) 保存到日志文件?

How to save python Errors (stderr) to a log file ONLY in case errors actually happen?

我有一个每分钟运行一次的 python 脚本。为了调试,我想创建带有 errors/exceptions 的文本文件以防它们出现。如果没有错误,我不需要任何日志文件。

编辑:我无法将所有代码包装在 try/except 循环中,因此 this 无济于事。

首先,我将 stderr 保存到 .txt 中:

sys.stderr = open('ERRORS_%s.txt' % (infile), 'a')
with open("%s_Error_Messages.txt" % (MSKSN), "a") as myfile:
    myfile.close()

其次,我尝试删除任何 raise SystemExit 位置之前的空 "%s_Error_Messages.txt" % (MSKSN) 文件,因为没有出现错误(否则,不会到达 raise SystemExit 位置)。

if os.path.getsize('ERRORS_%s.txt' % (infile)) == 0:
    os.remove('ERRORS_%s.txt' % (infile))

我得到的是WindowsError: [Error 32] The process cannot access the file because it is being used by another process。我认为这是因为只要脚本运行,stderr 总是被 python.exe 使用。

第一步,我也尝试过:

if sys.stderr != 0: 
   sys.stderr = open('ERRORS_%s.txt' % (infile), 'a')

这不起作用,因为 sys.stderr 永远不会为 0。

如何将 sys.stderr 写入 .txt 仅在实际错误的情况下?

除非你担心大量的错误数据,否则你可以直接将stderr重定向到一个stringIO对象,然后根据内容写出(或不写)

import StringIO
import sys

sys.stderr = StringIO.StringIO()
# do stuff
if sys.stderr.getvalue():
   with open ("path/to/log.txt") as output:
        output.write(sys.stderr.getvalue())

对于上下文管理器来说,这是一个很好的案例,它将设置替换标准错误,运行 您的代码,然后在完成后将标准错误重置回 sys.__stderr__

如果您无法在尝试中包装代码,您也可以尝试使用 sys.excepthook

设置此功能

由于接受的答案根本不起作用,这里是解决方案:

你说你不想要 try-except 机制,所以你可以使用 sys.excepthook 它在发生“未处理”异常时调用,并打印出给定的回溯和异常到 sys.stderr .每当你 运行 你的脚本,如果异常引发你的程序终止(因为你没有捕获它)但是你可以在你的文件中记录错误。

import sys

def myexcepthook(e_type, e_value, e_tb, org_excepthook=sys.excepthook):
    with open('errors.txt', 'a') as error_file:
        sys.stderr = error_file
        sys.stderr.write(f'--------------- Exception --------------\n')

        # Now this logs into our 'sys.stderr' which is 'error_file'.
        org_excepthook(e_type, e_value, e_tb)
        sys.stderr.write('\n')


sys.excepthook = myexcepthook

# This terminates the program here
1 / 0

print("You can see this only if an exception doesn't occur")

注意 :我可以直接写入文件,但我选择重定向让原始 sys.excepthook 记录它的相当回溯。如果您对 traceback 模块感到满意,您可以那样处理它。

这是运行ning 3次后的输出:

--------------- Exception --------------
Traceback (most recent call last):
  File "....", line 17, in <module>
    1 / 0
ZeroDivisionError: division by zero

--------------- Exception --------------
Traceback (most recent call last):
  File "....", line 17, in <module>
    1 / 0
ZeroDivisionError: division by zero

--------------- Exception --------------
Traceback (most recent call last):
  File "....", line 17, in <module>
    1 / 0
ZeroDivisionError: division by zero