python - 在 (i)python 脚本中从 jupyter 内核获取输出

标签 python ipython jupyter

我想在单个 ipython session 中打开多个内核,在这些内核上运行代码,然后收集结果。但我不知道如何收集结果,甚至看不到 stdout/stderr。我该如何做这些事情?

到目前为止我得到了什么

我已经使用如下代码完成了前两个步骤(打开内核并在其上运行代码):

from jupyter_client import MultiKernelManager
kernelmanager = MultiKernelManager()
remote_id = kernelmanager.start_kernel('python3')
remote_kernel = kernelmanager.get_kernel(remote_id)
remote = remote_kernel.client()
sent_msg_id = remote.execute('2+2')

[我欢迎任何有关如何改进它或如何关闭这些内核和客户端的建议。]

这里,python3 可以是我设置的任何内核的名称(可以在命令行使用 jupyter-kernelspec list 列出)。而且我似乎能够运行任何合理的代码来代替 '2+2'。例如,我可以写入一个文件,然后该文件就真的被创建了。

现在,问题是如何得到结果。我可以得到一些看似相关的消息

reply = remote.get_shell_msg(sent_msg_id)

那个回复是这样一个字典:

{'buffers': [],
 'content': {'execution_count': 2,
  'payload': [],
  'status': 'ok',
  'user_expressions': {}},
 'header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 378577),
  'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0',
  'msg_type': 'execute_reply',
  'session': 'ca4d615d-82b7-487f-88ff-7076c2bdd109',
  'username': 'me',
  'version': '5.0'},
 'metadata': {'dependencies_met': True,
  'engine': '868de9dd-054b-4630-99b7-0face61915a6',
  'started': '2015-10-19T14:34:34.265718',
  'status': 'ok'},
 'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0',
 'msg_type': 'execute_reply',
 'parent_header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 264508),
  'msg_id': '2674c61a-c79a-48a6-b88a-1f2e8da68a80',
  'msg_type': 'execute_request',
  'session': '767ae562-38d6-41a3-a9dc-6faf37d83222',
  'username': 'me',
  'version': '5.0'}}

这记录在 Messaging in Jupyter 中.没有记录的是如何实际使用它——即,我使用哪些功能,我何时何地找到消息等。我已经看到 this question及其答案,其中包含有用的相关信息,但并不能完全让我找到答案。和 this answer也没有得到任何有用的输出。

因此,例如,我也尝试使用上面结果中给出的 msg_id 获取 msg,但它只是挂起。我已经尝试了我能想到的一切,但无法弄清楚如何从内核中取回任何东西。我该怎么做?我可以以某种字符串的形式从内核传回数据吗?我可以看到它的标准输出和标准错误吗?

背景

我正在编写一个 ipython 魔术来在远程内核上运行代码片段。 [编辑:这现在存在并且可用here .] 我的想法是,我将在我的笔记本电脑上放一个笔记本,并通过像这样的一个小魔法单元从多个远程服务器收集数据:

%%remote_exec -kernels server1,server2
2+2
! hostname

我使用 remote_ikernel轻松自动地连接到那些远程内核。这似乎工作得很好;我得到了我的魔法命令,它所有的花里胡哨都运行良好,打开了这些远程内核,并运行了代码。现在我想从远程获取一些数据并发送回我的笔记本电脑——大概是通过某种方式将其序列化。目前,我认为pickle.dumpspickle.loads对这部分来说是完美的;我只需要将这些函数创建和使用的那些字节从一个内核传递到另一个内核。我宁愿不使用实际文件进行酸洗,尽管这可能是可以接受的。

编辑:

看起来像这样的怪物是可能的:

remote.get_shell_msg(remote.execute('import pickle'))
sent_msg_id = remote.execute('a=2+2', user_expressions={'output':'pickle.dumps({"a":a})'})
reply = remote.get_shell_msg(sent_msg_id)
output_bytes = reply['content']['user_expressions']['output']['data']['text/plain']
variable_dict = pickle.loads(eval(output_bytes))

现在,variable_dict['a'] 只是 4。但是请注意,output_bytes 是表示这些字节的字符串,因此必须对其进行eval。这看起来很荒谬(而且仍然没有显示我是如何获得标准输出的)。有没有更好的办法?我如何获得标准输出?

编辑2:

虽然我对上面的 hack 不满意,但我已经成功地使用它编写了一个名为 remote_exec 的小模块。托管在 github 上,如上所述。该模块给了我一点 ipython 魔法,我可以使用它在一个或多个其他内核上远程运行代码。这是一个或多或少的自动过程,我对此非常满意——除了对下面发生的事情的唠叨知识。

最佳答案

您似乎在重新发明轮子。您不想自己管理内核。使用类似 ipyparallel 的东西它制作用于产生许多内核并分散/收集数据(基本上您正在重新发明它的工作方式)。您可能还会对 dask 感兴趣并阅读 one introduction from the author . IPyparallel 和 dask 作者正在共同努力,使这两个项目能够很好地协同工作。 不要管理内核,而是使用 ipyparallel。

关于python - 在 (i)python 脚本中从 jupyter 内核获取输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33222141/

相关文章:

python - Spyder 和 Jupyter 有什么区别?

python - 在Jupyter notebook中,如何安排子程序才能高效地编写项目?

ssl - 更改 Jupyter 笔记本使用的 TLS 版本密码

python - 当 Python 中的输入量很大时如何有效地找到一个范围内的完美平方

Python Qt : How to catch "return" in qtablewidget

python - 如何从 python 等控制台使用 python 脚本中定义的方法

ipython - 有没有办法在 IPython notebook 中同时运行多个单元?

python - Cython 错误 : declaration does not declare anything

python - 如何以数值稳定的方式计算梯度

python - Cython ipython 魔术与编译时环境变量