在任何未捕获的异常上自动打印堆栈跟踪

时间:2011-09-28 14:24:41

标签: python debugging

如何自动在未捕获的任何异常情况下将堆栈跟踪打印到stdout?

我正在使用

pipe =  subprocess.Popen(cmd, shell=False, cwd=cwd, env=env,stdout=open(pth,'w'),stderr=open(pth,'w'))

在未捕获的异常中,该文件仅包含 未处理的例外: 但我还要将跟踪写入我的日志文件。

此外,如果异常被重新加入,我想要原始跟踪

由于

2 个答案:

答案 0 :(得分:0)

在子进程中初始化logging模块并分配sys.stdout = LoggerFile()。然后,子进程中未处理的任何异常都将写入您的日志文件而不是标准输出。如果您希望将其写入两者,请增强LoggerFile类。

请注意,因为子进程是一个完全独立的解释器,具有自己独立的执行堆栈,所以子进程中发生的异常不能传播回父进程。但您可以发送编码消息来模拟它。

from functools import partial
from itertools import imap

def text_coerce(encoding):
  u"given encoding returns function that takes bytes or characters and returns characters"
  def decode(data):
    u"if given characters returns them; if given bytes decodes them"
    if isinstance(data, StringType):  # really bytes
      return data.decode(encoding)
    else: return data
  return decode

def consume(iterable):
  u"consume all values from an iterable in a loop"
  while True:
    try:
      iterable.next()
    except StopIteration:
      break

class LoggerFile(object):
  u"a non-seekable character-based file-like object that logs all data written to it"
  def __init__(self, logger=None, level=logging.INFO, encoding='UTF-8'):
    if logger is None: logger = logging.getLogger()
    self._encoder = text_coerce(encoding)
    self._log = partial(logger.log, level)
    self.writelines = partial(map, self.write)
    self.close = lambda: None  # pretends to close
    self.flush = lambda: None  # pretends to flush
    self.mode = 'w'
  def write(self, message):
    u"write() results in exactly one log message; same for the print statement when replacing stdout"
    message = self._encoder(message).rstrip()
    if message != u'': self._log(message)
  def writelines(self, message):
    consume(imap(self.write, message.split(u'\n')))

答案 1 :(得分:0)

非常感谢所有人。 Wberry的解决方案有效,但没有必要。它只使用

工作正常
f = open(pth,'w');
pipe = subprocess.Popen(cmd,shell=False,cwd=cwd,env=env,stdout=f,stderr=f)

我的问题来自redifining excepthook其他地方(因此它启用了Eclipse的断点)。我修好了它(在需要时切换到原始sys.excepthook()。)

@patrys:我打开一次。这是一种误导性的一线捷径。道歉。