回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我想在一个ipython会话中打开几个内核,在这些内核上运行代码,然后收集结果。但我不知道如何收集结果,甚至无法查看stdout/stderr。我怎么能做这些事?在</p>
<h2>到目前为止我得到了什么</h2>
<p>我用如下代码管理了前两个步骤(打开内核并在其上运行代码):</p>
<pre><code>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')
</code></pre>
<p>[我欢迎任何关于如何改进这一点或如何关闭这些内核和客户端的建议。]</p>
<p>这里,<code>python3</code>可以是我设置的任何内核的名称(可以在命令行中用<code>jupyter-kernelspec list</code>列出)。我似乎可以运行任何合理的代码来代替<code>'2+2'</code>。例如,我可以写一个文件,而这个文件真的被创建了。在</p>
<p>现在的问题是如何得到结果。我能得到一些似乎与</p>
^{pr2}$
<p>这是一本这样的字典:</p>
<pre><code>{'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'}}
</code></pre>
<p>这在<a href="http://jupyter-client.readthedocs.org/en/latest/messaging.html" rel="nofollow noreferrer">Messaging in Jupyter</a>中有记录。没有被记录的是如何实际使用它——例如,我使用哪些函数,何时何地可以找到消息,等等。我已经看到了<a href="https://stackoverflow.com/q/29949881/1194883">this question</a>及其答案,其中包含有用的相关信息,但并不能完全帮助我找到答案。而且<a href="https://stackoverflow.com/a/9979553/1194883">this answer</a>也没有得到任何有用的输出。在</p>
<p>因此,例如,我也尝试使用上面的结果中给出的<code>msg_id</code>来获取msg,但它只是挂起了。我已经尝试了我能想到的一切,但是不知道如何从内核中获取任何东西。我该怎么做?我可以用某种字符串从内核传输回数据吗?我能看看它的stdout和stderr吗?在</p>
<h2>背景</h2>
<p>我正在编写一个ipython魔术来在远程内核上运行代码片段。[编辑:这个现在已经存在并且可以使用<a href="https://github.com/moble/remote_exec" rel="nofollow noreferrer">here</a>.]我的想法是在我的笔记本电脑上有一个笔记本,通过一个像这样的小魔法细胞从几个远程服务器收集数据:</p>
<pre><code>%%remote_exec -kernels server1,server2
2+2
! hostname
</code></pre>
<p>我使用<a href="https://bitbucket.org/tdaff/remote_ikernel/" rel="nofollow noreferrer">^{<cd5>}</a>轻松自动地连接到那些远程内核。这似乎运行得很好;我的魔法命令运行得很好,打开这些远程内核并运行代码。现在,我想从遥控器中获取一些数据,并将其发送回我的笔记本电脑——大概是通过某种方式将其序列化。目前,我认为<a href="https://docs.python.org/3.5/library/pickle.html#pickle.dumps" rel="nofollow noreferrer">^{<cd6>}</a>和{a7}非常适合这一部分;我只需要从一个内核到另一个内核获取这些函数创建和使用的字节。我宁愿不使用实际的文件进行酸洗,尽管这可能是可以接受的。在</p>
<h2>编辑:</h2>
<p>看起来像这样的怪物是有可能的:</p>
<pre><code>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))
</code></pre>
<p>现在,<code>variable_dict['a']</code>就是<code>4</code>。但是请注意,<code>output_bytes</code>是一个代表这些字节的字符串,因此它必须是<code>eval</code>ed的。这看起来很荒谬(而且仍然没有显示我如何获得stdout)。有更好的方法吗?我怎么得到stdout?在</p>
<h2>编辑2:</h2>
<p>尽管我对上面的方法不满意,但我已经成功地用它编写了一个名为<a href="https://github.com/moble/remote_exec" rel="nofollow noreferrer">^{<cd12>}</a>的小模块,托管在github上,如上所述。这个模块给了我一些ipython魔力,我可以用它在一个或多个其他内核上远程运行代码。这是一个或多或少自动化的过程,我肯定很满意——除了对下面发生的事情的喋喋不休的了解。在</p>