Python多处理示例不起作用

时间:2014-01-18 01:16:15

标签: python multiprocessing

我正在尝试学习如何使用multiprocessing,但我无法让它发挥作用。以下是documentation

中的代码
from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

应该输出

  
    

'你好鲍勃'

  

但我得到了

  
    

>

  

没有错误或其他消息,它只是坐在那里,它在IDLE中从一台带有32位版本的Python 2.7的Windows 7机器上保存的.py文件中运行

6 个答案:

答案 0 :(得分:13)

我的猜测是你正在使用IDLE来尝试运行这个脚本。不幸的是,这个例子在IDLE中无法正常运行。请注意the docs开头的注释:

  

注意此程序包中的功能需要 main   模块可由孩子们输入。这在编程中有所涉及   然而,值得指出的是指导方针。这意味着一些   示例,例如multiprocessing.Pool示例将不起作用   互动翻译。

IDLE中的子节点无法导入__main__模块,即使您将脚本作为具有IDLE的文件运行(通常使用F5)。

答案 1 :(得分:2)

有效。

我已经标记了使用评论运行示例所需的更改:

from multiprocessing import Process

def f(name):
print 'hello', name #indent

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()` # remove ` (grave accent)

结果:

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

将我的笔记本电脑保存为ex1.py后的输出:

reuts@reuts-K53SD:~/python_examples$ cat ex1.py 
#!/usr/bin/env python
from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
reuts@reuts-K53SD:~/python_examples$ python ex1.py 
hello bob

答案 2 :(得分:2)

问题不在于IDLE。问题是尝试在没有sys.stdout的进程中打印到sys.stdout。这就是Spyder遇到同样问题的原因。 Windows上的任何GUI程序都可能存在同样的问题。

在Windows上,至少GUI程序通常在没有stdin,stdout或stderr流的进程中运行。 Windows期望GUI程序通过在屏幕上绘制像素的小部件(图形中的G)与用户交互,并从Windows事件系统接收键和鼠标事件。这就是IDLE GUI所做的,使用tcl tk GUI框架的tkinter包装器。

当IDLE在子进程中运行用户代码时,idlelib.run首先运行,并且对于标准流替换None,其中对象通过套接字与IDLE本身交互。然后是exec()的用户代码。当用户代码运行多处理时,多处理启动没有std流的进一步进程,但永远不会得到它们。

解决方案是在控制台中启动IDLE:python -m idlelib.idle(3.x上不需要.idle)。进程在控制台中启动std流连接到控制台。那么进一步的子过程。所有进程的真正标准输出(与sys.stdout相对)是控制台。如果在文档中运行第三个示例,

from multiprocessing import Process
import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())

def f(name):
    info('function f')
    print('hello', name)

if __name__ == '__main__':
    info('main line')
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
然后是'主线' block转到IDLE shell和'函数f'块进入控制台。

这个结果表明Justin Barber声称由IDLE运行的用户文件无法导入到多处理启动的进程中是不正确的。

编辑:Python在sys.__stdout__中保存进程的原始标准输出。当IDLE在Windows上正常启动时,这是IDLE shell中的结果,作为纯GUI过程。

>>> sys.__stdout__
>>> 

以下是从CommandPrompt启动IDLE时的结果。

>>> import sys
>>> sys.__stdout__
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
>>> sys.__stdout__.fileno()
1

stdin,stdout和stderr的标准文件号是0,1,2。使用

运行文件
from multiprocessing import Process
import sys

def f(name):
    print('hello', name)
    print(sys.__stdout__)
    print(sys.__stdout__.fileno())
if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
IDLE中的

在控制台中启动,输出相同。

答案 3 :(得分:1)

很可能您的主进程在刷新sysout之前退出。试试这个:

from multiprocessing import Process
import sys

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
    # make sure all output has been processed before we exit
    sys.stdout.flush()

如果这不起作用,请尝试添加time.sleep(1)作为最后一个语句。

答案 4 :(得分:0)

我遇到了多处理无法在Spyder上运行的问题,而且总是落在这里。我通过使用线程而不是多处理来解决它。如下所述:https://pymotw.com/2/threading/

import threading
def worker(num):
    """thread worker function"""
    print 'Worker: %s' % num
    return
threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()

答案 5 :(得分:0)

尝试使用此代码(来自标准手册)。在 Windows 上对我有用。另一个也不适合我:)

ProxyPass /tomcat http://localhost:8080/tomcat