【问题标题】:How to save errors from Jupyter Notebook cells to a file?如何将 Jupyter Notebook 单元格中的错误保存到文件中?
【发布时间】:2017-12-12 17:37:52
【问题描述】:

我正在尝试将单元格的所有输出(标准输出和所有错误)保存到文件中。为了保存标准输出,我使用以下内容:

import sys
old_stdout = sys.stdout
sys.stdout = open('test.txt', 'w')
print("Hello World! ")

在这种情况下,输出不会显示并按预期保存在文件中。为了保存错误,我使用了:

#Doesn't work
sys.stderr = open('error.txt','w')
print(a) #Should raise NameError

当我运行这个单元格时,我在笔记本中得到错误,而不是在文件中如预期的那样:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-de3efd936845> in <module>()
      1 #Doesn't work
----> 2 sys.stderr = open('error.txt','w')
      3 print("Test")
      4 print(a)

NameError: name 'sys' is not defined

我希望将其保存在一个文件中,而不是在笔记本中显示。正确的代码是什么?

【问题讨论】:

标签: python python-2.7 jupyter-notebook


【解决方案1】:

认为这里的问题是为 notebook 生成的 IPython 内核使用了一个 ZMQInteractiveShell 实例,它在错误到达 stderr 之前捕获错误,以便将错误信息发送到各种潜在的前端(控制台、jupyter 笔记本等)。请参阅ipykernel/ipkernel.py#L397-L413 了解捕获异常的代码,然后参阅InteactiveShell._showtraceback 了解基本实现(打印到sys.stderr),以及ZMQInteractiveShell._showtraceback 了解笔记本内核使用的代码(通过zmq 向前端发送stderr-channel 消息)。

如果您不介意获得准确的 stderr 输出,您可以利用 IPython 的 existing error logging,它将错误记录到前缀为 "Exception in execute request:"StreamHandler。要使用它,请设置 ipython 日志级别,并更改提供的处理程序的流:

import logging
import sys

my_stderr = sys.stderr = open('errors.txt', 'w')  # redirect stderr to file
get_ipython().log.handlers[0].stream = my_stderr  # log errors to new stderr
get_ipython().log.setLevel(logging.INFO)  # errors are logged at info level

或者,要让您的 shell 错误直接打印到文件而不进行更改,您可以猴子修补 _showtraceback 方法以打印回溯到文件以及 zmq 消息队列:

import sys
import types

# ensure we don't do this patch twice
if not hasattr(get_ipython(), '_showtraceback_orig'):
    my_stderr = sys.stderr = open('errors.txt', 'w')  # redirect stderr to file
    # monkeypatch!
    get_ipython()._showtraceback_orig = get_ipython()._showtraceback

    def _showtraceback(self, etype, evalue, stb):
        my_stderr.write(self.InteractiveTB.stb2text(stb) + '\n')
        my_stderr.flush()  # make sure we write *now*
        self._showtraceback_orig(etype, evalue, stb)

    get_ipython()._showtraceback = types.MethodType(_showtraceback, get_ipython())

【讨论】:

  • 感谢您的解释。然而,这段代码并没有达到预期的效果: import logging import sys sys.stderr = open('errors.txt', 'w') # redirect stderr to file get_ipython().log.setLevel(logging.INFO) A NameError is未记录在错误日志文件中。对于第二段代码,此行会引发错误: print(self.InteractiveTB.stb2text(stb), file=sys.stderr) 我不太理解这段代码,因此无法调试错误。你能运行一次并检查它是否对你有用吗?我有 python 2.7,如果这很重要的话。
  • 不确定为什么第一个变体对您不起作用,是否值得刷新文件?我明天必须在电脑上查看
  • 第二个变体需要对 python 2 稍作改动,因为打印语法不同,你可以试试sys.stderr.write(self.InteractiveTB.stb2text(stb) + '\n') 代替吗?
  • 好的,我已经更新了两个 python sn-ps 以希望解决这两个问题 ;)
  • 谢谢。像魅力一样工作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 2017-04-25
  • 2021-02-16
  • 1970-01-01
  • 2020-06-09
  • 2020-02-15
  • 1970-01-01
相关资源
最近更新 更多