在IPython并行进程中向stdout打印
我刚接触IPython,想在运行IPython并行集群函数时,把中间结果打印到标准输出(stdout)。我知道因为有多个进程,这可能会让输出变得混乱,但没关系——这只是为了测试和调试,而且我运行的进程比较长,所以这种冲突发生的可能性不大。我查了IPython的文档,但找不到一个示例,说明并行化的函数是如何打印输出的。
简单来说,我想找到一种方法,把子进程的打印输出重定向到主标准输出,也就是IPython中的等价方式。
subprocess.Popen( ... , stdout=...)
在进程内部打印是行不通的:
rc = Client()
dview = rc()
def ff(x):
print(x)
return x**2
sync = dview.map_sync(ff,[1,2,3,4])
print('sync res=%s'%repr(sync))
async = dview.map_async(ff,[1,2,3,4])
print('async res=%s'%repr(async))
print(async.display_outputs())
返回的结果是
sync res=[1, 4, 9, 16]
async res=[1, 4, 9, 16]
所以计算是正确执行的,但在函数ff中的打印语句从来没有被打印出来,即使所有进程都已经返回了。我哪里做错了?我该如何让“打印”工作?
1 个回答
9
其实这和 subprocess.Popen( ... , stdout=PIPE)
更像,而不是你想的那样。就像 Popen
对象有一个 stdout
属性,你可以通过这个属性查看子进程的标准输出一样,AsyncResult
也有一个 stdout
属性,它包含了从引擎捕获的标准输出。
不过有一点不同的是,AsyncResult.stdout
是一个字符串列表,列表中的每一项都是一个引擎的标准输出,都是字符串形式。
那么,首先:
rc = parallel.Client()
dview = rc[:]
def ff(x):
print(x)
return x**2
sync = dview.map_sync(ff,[1,2,3,4])
print('sync res=%r' % sync)
async = dview.map_async(ff,[1,2,3,4])
print('async res=%r' % async)
async.get()
会得到
sync res=[1, 4, 9, 16]
async res=<AsyncMapResult: ff>
我们可以看到 AsyncResult.stdout
的字符串列表:
print(async.stdout)
['1\n2\n', '3\n4\n']
我们可以看到异步结果的标准输出:
print('async output:')
async.display_outputs()
打印出来的是:
async output:
[stdout:0]
1
2
[stdout:1]
3
4
还有这里有一个示例笔记本,展示了所有这些内容。
根据你的问题,有几点需要注意:
- 你必须等到
AsyncResult
完成后,输出才会准备好(使用async.get()
)。 display_outputs()
不会返回任何东西——它实际上是自己负责打印和显示的,所以print(async.display_outputs())
是没有意义的。