【问题标题】:Python multiprocessing example not workingPython多处理示例不起作用
【发布时间】:2014-01-18 01:16:15
【问题描述】:

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

它应该输出

'你好鲍勃'

但是我得到了

>

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

【问题讨论】:

  • 你的 print 语句真的不打算在 def 下吗?
  • @Green 你的意思是缩进吗?是的,它在实际代码中正确缩进,这是我在发布时犯的错误
  • 您是否将代码保存在文件中并运行它?
  • @ReutSharabani 是的,我做到了,这有关系吗?
  • @ChuckFulminata 只是确保你不是从 REPL 做的事情。

标签: python multiprocessing


【解决方案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) 作为最后一条语句。

【讨论】:

  • 虽然这可能有效,但请记住此代码是文档中的逐字记录,另一位发帖人已经指出它有效
  • 代码没问题,就是看不到输出。多处理行为取决于您运行它的特定机器,而您的机器可能快到足以在您看到输出之前吞下它。
  • 投反对票,但请留下评论,以便我改进答案。
  • 当没有要刷新的标准输出时,刷新不是问题。有一个标准输出流解决了这个问题。看我的回答。
【解决方案2】:

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

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

当 IDLE 在子进程中运行用户代码时,idlelib.run 首先运行,它用通过套接字与 IDLE 自身交互的对象替换标准流的 None。然后它执行()的用户代码。当用户代码运行 multiprocessing 时,multiprocessing 会启动更多没有 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()

然后“主线”块进入 IDLE shell,“函数 f”块进入控制台。

这个结果表明,Justin Barber 声称 IDLE 运行的用户文件不能导入到 multiprocessing 启动的进程中是不正确的。

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

>>> 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】:

    我遇到了多处理在 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()
    

    【讨论】:

    • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
    • Sami,如果你可以从控制台命令行启动 Spyder,输出应该是可见的,因为它是 IDLE。 (您是在 Windows 上运行还是 ???。)
    • 特里,我还没有尝试过,是的,我正在 Windows 上运行它。 Karl:谢谢,我已经添加了示例。
    【解决方案4】:

    有效。

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

    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
    

    【讨论】:

    • 这两个都是我发布问题时犯的错误,实际代码中都没有出现,不会做任何事情
    • 如您所见,此代码确实有效。要么您没有使用我发布的相同代码,要么问题不在于代码。你在哪里运行代码?你是如何运行它的?需要更多信息。
    • 这个问题可能是Windows特有的,我不知道。即使在 Windows 上,如果从命令行运行 IDLE,输出也是可见的。看我的回答。
    【解决方案5】:

    我的猜测是您正在使用 IDLE 来尝试运行此脚本。不幸的是,这个例子在 IDLE 中不能正确运行。注意the docs开头的注释:

    注意此包中的功能需要 ma​​in 模块可由孩子们导入。这在编程中有所介绍 指南但是值得在这里指出。这意味着一些 示例,例如 multiprocessing.Pool 示例将不起作用 交互式解释器。

    __main__ 模块不能由 IDLE 中的子级导入,即使您将脚本作为具有 IDLE 的文件运行(通常使用 F5 完成)。

    【讨论】:

    • 我不是从交互式解释器运行它
    • @Chuck Fulminata 你从哪里运行它?
    • 一个保存在硬盘上的.py文件
    • @Chuck Fulminata 你是怎么运行那个文件的?
    • @Chuck Fulminata 这正是问题所在。这行不通,因为 IDLE 中的子级无法导入 __main__ 模块,即使您将脚本作为 .py 文件运行也是如此。
    【解决方案6】:

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

    import multiprocessing as mp
    
        def foo(q):
            q.put('hello')
        
        if __name__ == '__main__':
            mp.set_start_method('spawn')
            q = mp.Queue()
            p = mp.Process(target=foo, args=(q,))
            p.start()
            print(q.get())
            p.join()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-05
      • 2019-03-12
      • 2014-11-13
      • 2013-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多