Jupyter Notebook Logging ValueError: I/O Operation on Closed File

Posted

技术标签:

【中文标题】Jupyter Notebook Logging ValueError: I/O Operation on Closed File【英文标题】: 【发布时间】:2019-05-07 16:53:02 【问题描述】:

我正在尝试将日志记录添加到一些 Jupyter Notebook 代码(运行 Pyspark3)。

四处挖掘,我发现一些答案说使用 basicConfig() 不起作用,因为笔记本启动了自己的日志记录会话。一些解决方法的答案指向运行reload(logging) 来解决这个问题。考虑到这一点,我正在像这样设置我的日志记录:

from importlib import reload  # Not needed in Python 2
import logging
reload(logging)
logging.basicConfig(
    format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
    level=logging.INFO,
    datefmt="%y/%m/%d %H:%M:%S",
)
logger = logging.getLogger(__name__)

然后我运行一条 info 语句:logger.info("this is a test") 并收到 I/O 值错误?我不确定这意味着什么。

--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib64/python3.6/logging/__init__.py", line 994, in emit
    stream.write(msg)
  File "/tmp/2950371398694308674", line 534, in write
    super(UnicodeDecodingStringIO, self).write(s)
ValueError: I/O operation on closed file
Call stack:
  File "/tmp/2950371398694308674", line 700, in <module>
    sys.exit(main())
  File "/tmp/2950371398694308674", line 672, in main
    response = handler(content)
  File "/tmp/2950371398694308674", line 318, in execute_request
    result = node.execute()
  File "/tmp/2950371398694308674", line 229, in execute
    exec(code, global_dict)
  File "<stdin>", line 1, in <module>
Message: 'this is a test'
Arguments: ()

这与记录与 stdout/stderr 交互有关,但我不确定如何解决。

【问题讨论】:

我遇到了同样的错误。这是由于笔记本环境与logging内置的python模块没有很好的配合造成的。我试图捕捉错误并忽略它,因为日志记录确实发生了。如果我成功将发布代码。 哦,太好了!请分享。 在这方面工作了一段时间,但没有想出解决办法。难以重现。如果我将有问题的代码复制到一个新的笔记本中,它就会正常运行。 有趣。那么这可能与我的环境有关吗?我在 EMR 集群(版本 5.29.0)上运行它。 对我来说,它只发生在 jupyter 笔记本中,并且只有当我在其中有很多代码时才会发生。如果我将最小版本粘贴到新笔记本中,我不会收到错误消息。 【参考方案1】:

在我上面的评论之后,我来解决这个问题。

问题似乎是sys.stdout 不能很好地与spark 配合使用,或者至少在被jupyter 使用时;您可以通过制作一个新的 (Pyspark3) 笔记本轻松验证这一点,导入 sys,然后在不同的单元格中打印 sys.stdout:它们将打印不同的对象(在我的情况下,有 4 个对象,并且在它们之间循环,但是我不能确定为什么是 4;也许它是我的集群配置所特有的,但它没有改变,因为我改变了 exec 的数量,或者每个 exec 的核心)。

我的解决方法是:

logger = logging.getLogger(__name__)
logger.handlers[0].stream.write = print

这很有效,因为我知道我的记录器只有一个处理程序,它是sys.stdout。如果您的记录器中有更多处理程序(例如,一个标准输出和一个文件),我还没有弄清楚如何仅更改 stdout 一个(我无法比较 if stream == sys.stdout 因为问题的整个根源意味着对象将发生变化,除非您在创建记录器的同一单元格中执行此操作),因此此解决方法可能并不适合所有人。

如果我进一步发展,我会用更好的解决方案编辑答案,但我现在正在使用它,它就像一个魅力。

【讨论】:

以上是关于Jupyter Notebook Logging ValueError: I/O Operation on Closed File的主要内容,如果未能解决你的问题,请参考以下文章

jupyter notebook 更换路径

如何修改jupyter notebook的默认工作路径

jupyter notebook怎么加环境变量

Jupyter Notebook——如何显示目录的导航栏(安装 Jupyter Notebook extension)

jupyter notebook 启动不起来

jupyter notebook 找不到命令