【问题标题】:Trying to understand Multiprocessing with main in python试图用python中的main来理解多处理
【发布时间】:2012-04-09 01:32:18
【问题描述】:

使用下面的代码,我得到了奇怪的输出:

import  sys 
from  multiprocessing import Process
import time
from time import strftime

now =time.time()    
print time.strftime("%Y%m%d %H:%M:%S", time.localtime(now)) 

fr= [1,2,3]
for row in fr:
    print 3

print 1

def worker():
    print 'worker line'
    time.sleep(1)
    sys.exit(1)

def main():
    print 'start worker'
    Process(target=worker, args=()).start()
    print 'main line'

if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    duration = end_time - start_time
    print "Duration: %s" % duration

输出是:

20120324 20:35:53
3
3
3
1
start worker
main line
Duration: 0.0
20120324 20:35:53
3
3
3
1
worker line 

我想我会得到这个:

20120324 20:35:53
3
3
3
1
start worker
worker line
main line
Duration: 1.0

为什么要运行两次?在 WinX64 上使用 python 2.7:

20120324 20:35:53
3
3
3
1
worker line 

【问题讨论】:

    标签: python multiprocessing main


    【解决方案1】:

    问题基本上是因为multiprocessing 确实设计为在posix 系统上运行,一个带有fork(2) 系统调用的系统。在那些操作系统上,进程可以一分为二,子进程神奇地从父进程克隆状态,并且两个进程都在同一个地方恢复运行,子进程现在有了一个新的进程 ID。在这种情况下,multiprocessing 可以根据需要安排某种机制将状态从父级传送到子级,并确保子级已经拥有大部分所需的 python 状态。

    Windows 没有fork()

    所以multiprocessing 必须收拾残局。这基本上涉及启动一个运行多处理子脚本的全新 python 解释器。几乎立即,父母会要求孩子使用处于父母状态的东西,因此孩子将不得不从头开始重新创建该状态,通过将您的脚本导入孩子

    因此,在脚本中导入时发生的任何事情都会发生两次,一次在父级中,另一次在子级中,因为它重新创建了为父级提供服务所需的 python 环境。

    【讨论】:

    • 但是为什么看起来脚本运行了两次而只有工作人员运行了两次?如果我调用了一个模块或另一个脚本,而不是 print 1,那么该模块/脚本是否也会运行两次......我将如何控制启动的进程数。
    • 不是worker跑了两次,是worker跑了一次,'parent'跑了一次。当您执行python myscript.py 时,所有顶级代码都会执行,但是当您的脚本调用multiprocessing.Process()(执行python -m multiprocessing.child,然后执行import myscript)时,它会重新运行。
    【解决方案2】:

    这是我使用 Python 2.7.3 在 Linux 上运行您的代码时得到的结果:

    20120324 23:05:49
    3
    3
    3
    1
    start worker
    main line
    Duration: 0.0045280456543
    worker line
    

    我不知道为什么你的运行两次,但我可以告诉你为什么它没有返回预期的持续时间或以“正确”的顺序打印。

    当您使用multiprocessing 启动进程时,启动是异步的。即.start()函数在父进程中立即返回,这样父进程可以继续工作并做其他事情(比如启动更多进程),而子进程在后台做自己的事情。如果您想阻止父进程继续进行直到子进程结束,您应该使用.join() 函数。像这样:

    def main():
        print 'start worker'
        p = Process(target=worker, args=())
        p.start()
        p.join()
        print 'main line'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多