在 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
常规的stderr
和stdout
流似乎仍然连接到该终端,而笔记本会话将在新的浏览器窗口中开始。在笔记本中运行发布的代码 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 种配置中进行了测试。确认将multiprocessing
和threading
用于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