在IPython并行处理中将内容打印到标准输出

8

我是IPython的新手,想在运行IPython并行集群函数时将中间结果打印到标准输出。 (我知道使用多个进程可能会破坏输出,但这没关系--这只是为了测试/调试,并且我要运行的进程足够长,不太可能发生这样的冲突。) 我查看了IPython的文档,但找不到并行化函数打印输出的示例。 基本上,我正在寻找一种将子进程的打印输出重定向到主stdout的方法,这是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中的打印语句从未打印,即使所有进程都返回也是如此。 我做错了什么?我该如何让“print”起作用?

1个回答

9
它实际上与 subprocess.Popen(..., stdout=PIPE) 更相似,比您预期的更相似。 就像 Popen 对象具有 stdout 属性一样,您可以读取它以查看子进程的 stdout, AsyncResult 也具有 stdout 属性,其中包含从引擎捕获的 stdout。 不同之处在于 AsyncResult.stdout 是字符串列表,其中列表中的每个项都是单个引擎的 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

以下是与您的问题相关的一些注意事项:

  1. 在输出准备好之前,必须等待AsyncResult完成(使用async.get())。
  2. display_outputs()不返回任何内容 - 它实际上执行打印/显示操作,因此print(async.display_outputs())没有意义。

这里是一个notebook演示所有这些内容:here is a notebook


非常有帮助的答案。在计算过程中是否有任何方法可以查看stdout输出? - spencerlyon2
是的 - 对于打印语句,只需执行 for out in asyncresult.stdout: print out 即可,您可以在任何时候执行此操作,即使输出是部分的。 - minrk
1
有没有一种方法可以在没有访问源代码的情况下实现这一点?我正在使用一个库,在线程中打印日志消息,我希望它在运行时打印。我需要扩展IPython的类来实现这个吗? - hgcrpd
display_outputs 不是针对长时间任务的实时打印。 - huang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接