Python多处理示例不起作用

2024-05-12 00:00:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力学习如何使用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()

它应该输出

'hello bob'

但我却得到了

>

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


Tags: 代码namefromimporthellotargetifmain
3条回答

问题不在于无所事事。问题是试图在没有sys.stdout的进程中打印到sys.stdout。这就是为什么Spyder也有同样的问题。Windows上的任何GUI程序都可能有同样的问题。

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

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

解决方案是在控制台中启动空闲: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()

然后“main line”块进入空闲shell,“function f”块进入控制台。

这一结果表明,Justin Barber关于IDLE运行的用户文件不能导入到多处理启动的进程中的说法是不正确的。

编辑:Python在sys.__stdout__中保存进程的原始stdout。以下是在Windows上正常启动IDLE时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来运行这个脚本。不幸的是,这个示例在空闲时不能正确运行。注意the docs开头的注释:

Note Functionality within this package requires that the main module be importable by the children. This is covered in Programming guidelines however it is worth pointing out here. This means that some examples, such as the multiprocessing.Pool examples will not work in the interactive interpreter.

__main__模块不可由处于空闲状态的子模块导入,即使您将脚本作为具有空闲状态的文件运行(通常使用F5完成)。

它起作用了。

我已使用注释标记了运行示例所需的更改:

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

相关问题 更多 >