在 jupyter notebook 中使用 joblib 时不显示打印输出

Posted

技术标签:

【中文标题】在 jupyter notebook 中使用 joblib 时不显示打印输出【英文标题】:Printed output not displayed when using joblib in jupyter notebook 【发布时间】:2019-09-21 03:29:51 【问题描述】:

所以我使用joblib 来并行化一些代码,我注意到在 jupyter 笔记本中使用它时无法打印。

我尝试在 ipython 中使用相同的示例,并且效果很好。

这是一个在 jupyter 笔记本单元格中编写的最小(非)工作示例

from joblib import Parallel, delayed
Parallel(n_jobs=8)(delayed(print)(i) for i in range(10))

所以我得到了[None, None, None, None, None, None, None, None, None, None] 的输出,但没有打印任何内容。

我期望看到的(实际打印顺序可能是随机的):

1
2
3
4
5
6
7
8
9
10
[None, None, None, None, None, None, None, None, None, None]

注意:

您可以在笔记本进程的日志中看到打印。但我希望打印发生在笔记本中,而不是笔记本进程的日志中。

编辑

我打开了一个Github issue,但到目前为止很少有人关注。

【问题讨论】:

【参考方案1】:

我认为这部分是由于Parallel 产生子工作者的方式,以及 Jupyter Notebook 如何为这些工作者处理 IO。在没有为backend 指定值的情况下启动时,Parallel 将默认为loky,它利用直接使用 fork-exec 模型创建子进程的池化策略。

如果您使用

从终端启动 Notebook
$ jupyter-notebook

常规的stderrstdout 流似乎仍然连接到该终端,而笔记本会话将在新的浏览器窗口中开始。在笔记本中运行发布的代码 sn-p 确实会产生预期的输出,但它似乎会转到 stdout 并最终出现在终端中(如 Note中所暗示的) > 在问题中)。这进一步支持了这种行为是由loky 与 notebook 之间的交互以及 notebook 为子进程处理标准 IO 流的方式引起的怀疑。

这将我带到了 github 上的 this discussion(在发布后的过去 2 周内活跃),notebook 的作者似乎意识到了这一点,但似乎没有明显且快速的解决方案目前的问题。

如果您不介意切换 Parallel 用于生成子代的后端,您可以这样做:

from joblib import Parallel, delayed
Parallel(n_jobs=8, backend='multiprocessing')(delayed(print)(i) for i in range(10))

使用multiprocessing 后端,一切正常。 threading 看起来也可以正常工作。这可能不是您希望的解决方案,但希望在笔记本作者努力寻找合适的解决方案时它就足够了。

我会将这个交叉发布到 GitHub,以防有人愿意添加到这个答案中(我不想误报任何人的意图或把话放在人们的嘴里!)。


测试环境: MacOS - 莫哈韦 (10.14) Python - 3.7.3 pip3 - 19.3.1

在 2 种配置中进行了测试。确认将multiprocessingthreading 用于backend 参数时产生预期的输出。使用pip3 安装软件包。

设置 1:

ipykernel                               5.1.1
ipython                                 7.5.0
jupyter                                 1.0.0
jupyter-client                          5.2.4
jupyter-console                         6.0.0
jupyter-core                            4.4.0
notebook                                5.7.8

设置 2:

ipykernel                               5.1.4
ipython                                 7.12.0
jupyter                                 1.0.0
jupyter-client                          5.3.4
jupyter-console                         6.1.0
jupyter-core                            4.6.2
notebook                                6.0.3

我也成功使用了与“设置 2”相同的版本,但将 notebook 软件包版本降级为 6.0.2。

注意:

此方法在 Windows 上的工作方式不一致。软件版本的不同组合产生不同的结果。做最直观的事情 - 将所有内容升级到最新版本 - 并不能保证它会起作用。

【讨论】:

我可以确认这在 Colab 中有效,但是我刚刚使用 Jupyter Notebook v6.0.2 和 JupyterLab v1.2.4 (Python v3.6.8) 进行了测试,但两者都不起作用,我只是看到stdout 中的打印并获取 None 返回的数组。您使用的是哪个版本的 Jupyter Notebook? 我更新了答案以包含有关测试环境的详细信息。除了 6.0.3 之外,我使用您提到的两个版本的 Notebook 都得到了预期的结果。我使用的是 Python 3.7,但如果这是问题所在,我会感到有些惊讶。你是如何安装软件包的?您使用的是 MacOS/Linux,还是使用 Windows? 我使用的是 Windows,这实际上可能有所不同。 我确认它可以在 Linux 上运行。我想我们发现了另一个仅与 Windows 相关的错误。请更新您的答案以提及这一点。感谢您的帮助,这个问题让我很头疼! :-) @spizwhiz 实际上昨天刚刚检查过这个。不幸的是,自 2 月以来,讨论此问题的 GitHub 上的线程没有太多活动,所以我怀疑在不久的将来会有修复。【参考方案2】:

在 Z4-tier 的 git link scottgigante 的方法在 Windows 中工作,但与提到的结果相反:在 Jupyter notebook 中,“多处理”后端永远挂起,但默认的 loky 运行良好(python 3.8.5 和 notebook 6.1.1 ):

from joblib import Parallel, delayed
import sys
def g(x):
    stream = getattr(sys, "stdout")
    print("".format(x), file=stream)
    stream.flush()
    return x
Parallel(n_jobs=2)(delayed(g)(x**2) for x in range(5))

executed in 91ms, finished 11:17:25 2021-05-13
[0, 1, 4, 9, 16]

更简单的方法是延迟使用恒等函数:

Parallel(n_jobs=2)(delayed(lambda y:y)([np.log(x),np.sin(x)]) for x in range(5))
executed in 151ms, finished 09:34:18 2021-05-17
[[-inf, 0.0],
 [0.0, 0.8414709848078965],
 [0.6931471805599453, 0.9092974268256817],
 [1.0986122886681098, 0.1411200080598672],
 [1.3862943611198906, -0.7568024953079282]]

或者这样使用:

Parallel(n_jobs=2)(delayed(lambda y:[np.log(y),np.sin(y)])(x) for x in range(5))
executed in 589ms, finished 09:44:57 2021-05-17
[[-inf, 0.0],
 [0.0, 0.8414709848078965],
 [0.6931471805599453, 0.9092974268256817],
 [1.0986122886681098, 0.1411200080598672],
 [1.3862943611198906, -0.7568024953079282]]

【讨论】:

以上是关于在 jupyter notebook 中使用 joblib 时不显示打印输出的主要内容,如果未能解决你的问题,请参考以下文章

Jupyter Lab 在错误的路径中打开,与 Jupyter Notebook 不同,两者在“jupyter_notebook_config.py”中具有相同的映射。

如何在Jupyter Notebook中使用Python虚拟环境?

在 jupyter notebook 中使用 joblib 时不显示打印输出

解决不能再jupyter notebook中使用tensorflow

Jupyter Lab 中的 Jupyter Notebook 扩展

Jupyter notebook 中 从url中load 数据集, 会存在哪里?