开发者

automatically print stack trace on any uncaught exception

开发者 https://www.devze.com 2023-04-09 05:27 出处:网络
How can I automatically print the stack trace to stdout on any uncaught exceptions ? I am using pipe =subprocess.Popen(cmd, shell=False, cwd=cwd, env=env,stdout=open(pth,\'w\'),stderr=open(pth,\'w\

How can I automatically print the stack trace to stdout on any uncaught exceptions ?

I am using

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

On uncaught Exception, the file will only contain Unhandled Exception: but I'd like in addition the trace to be written to my logfile.

Moreover I'd like 开发者_C百科the original trace if the exception had been reraised

Thanks


In the child process initialize the logging module and assign sys.stdout = LoggerFile(). Then any exception not handled within the child process will be written to your log file instead of to standard out. If you want it to be written to both, enhance the LoggerFile class.

Please note that because the child process is a completely separate interpreter, with its own separate execution stack, exceptions occurring within the child process cannot be propagated back to the parent process. But you could send encoded messages to simulate that.

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')))


Thanks a lot to all. Wberry's solution works but is not necessary. It works fine using just

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

My problem came from redifining excepthook somewhere else (so that it enables Eclipse's breakpoint). I fixed it (switching to original sys.excepthook() when needed).

@patrys: I open it once. It was a misleading one-line shortcut. Apologies.

0

精彩评论

暂无评论...
验证码 换一张
取 消