Python多处理示例不起作用

Dev*_*oka 11 python multiprocessing

我正在努力学习如何使用,multiprocessing但我无法让它工作.以下是文档中的代码

from multiprocessing import Process

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

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
Run Code Online (Sandbox Code Playgroud)

它应该输出

'你好鲍勃'

但我得到了

>

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

πόδ*_*κύς 15

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

注意此程序包中的功能要求 模块可由子项导入.这在编程指南中有所涉及,但值得在此指出.这意味着某些示例(例如multiprocessing.Pool示例)在交互式解释器中不起作用.

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

  • @Chuck Fulminata这正是问题所在.这是行不通的,因为IDLE中的子进程无法导入`__main__`模块,即使您将脚本作为.py文件运行也是如此. (2认同)

Ter*_*edy 9

问题不是空闲。问题是试图在没有 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 首先运行,它用通过套接字与 IDLE 本身交互的对象替换标准流的 None 。然后它 exec() 的用户代码。当用户代码运行 multiprocessing 时,multiprocessing 会启动没有 std 流的进一步进程,但永远不会得到它们。

解决的办法是在控制台启动IDLE: python -m idlelib.idle(在.idle不需要上3.X)。在控制台中启动的进程将 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()
Run Code Online (Sandbox Code Playgroud)

然后'main line'块进入IDLE shell,'function f'块进入控制台。

这个结果表明,贾斯汀·巴伯关于 IDLE 运行的用户文件无法导入到由多进程启动的进程的说法是不正确的。

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

>>> sys.__stdout__
>>> 
Run Code Online (Sandbox Code Playgroud)

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

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

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()
Run Code Online (Sandbox Code Playgroud)

在控制台中启动IDLE并且输出是相同的。