在Jupyter Notebook中使用Joblib时不显示打印输出

时间:2019-05-02 15:07:06

标签: python printing jupyter-notebook jupyter joblib

所以我正在使用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],但是什么也没打印。

实际上,在检查笔记本进程的日志时,我注意到打印在那里发生。我希望打印发生在笔记本中,而不是笔记本过程的日志中。

2 个答案:

答案 0 :(得分:6)

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

如果您使用

从终端启动Notebook
$ jupyter-notebook

常规stderrstdout流似乎仍然连接到该终端,而笔记本会话将在新的浏览器窗口中启动。在笔记本中运行发布的代码段 会产生预期的输出,但是它似乎到达了stdout并最终到达了终端(如 Note 中所提示>)。这进一步证实了这种行为是由loky与笔记本之间的交互作用以及笔记本为子进程处理标准IO流的方式引起的怀疑。

这导致我转到github上的this discussion(在本贴子发布之日起过去两周内有效),笔记本的作者似乎已经意识到了这一点,但是似乎没有明显且快速的解决方案解决目前的问题。

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

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

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

我将把它交叉发布到GitHub上,以防万一有人想添加到这个答案中(我不想误解任何人的意图或在人们的嘴里说出来!)。


测试环境:
MacOS-Mojave(10.14)
Python-3.7.3
pip3-19.3.1

在2种配置中测试。确认同时为multiprocessing使用threadingbackend时产生预期的输出。软件包使用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上不一致。软件版本的不同组合会产生不同的结果。做最直观的事情-将所有内容升级到最新版本-不能保证它会起作用。

答案 1 :(得分:0)

在 Z4 层的 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]]