multiprocessing 与平台有关

2017-01-05 21:34:43 +08:00
 wisefree

今天遇到了一个很让人费解的问题。问题的起因是没有把多进程程序写在 __main__下面( windows 系统下) 然后就尴尬了。

以前学习多进程是在 Linux 下,用的较多的是 fork ,今天遇到的问题,很有意思,所以就写下来。

# -*- coding: utf-8 -*-
__author__ = 'bigboydream'

import random
from multiprocessing import Process
import os

print('I am ', os.getpid())
rand_num = random.randint(0, 20)

def foo():
    print('I am {}, rand_num is {}'.format(os.getpid(), rand_num))   # 子进程的 rand_num

if __name__ == "__main__":
    print('I am {}, rand_num is {}'.format(os.getpid(), rand_num))  # 父进程的 rand_num
    p = Process(target=foo)
    p.start()
    p.join()

'''
I am  16880              
I am 16880, rand_num is 10   
I am  7592             # 执行了两次 print('I am ', os.getpid())...
I am 7592, rand_num is 2   # 父进程和子进程的 rand_num 居然不一样...
'''

用 fork 的思维想了一下 第一: print('I am ', os.getpid()),应该只能执行一次啊 第二: rand_num 应该一样啊

但是出现了不一样的结果,难道 p.start()的时候,

import random
from multiprocessing import Process
import os

print('I am ', os.getpid())
rand_num = random.randint(0, 20)
'''
又执行了一遍!!!
'''

所以得到了以上的结果。

难怪多进程程序不写在__main__下面会出现错误,不然就一直在递归地创建子进程了。

一样的代码在 Linux 下运行

# -*- coding: utf-8 -*-
__author__ = 'bigboydream'

import random
from multiprocessing import Process
import os

print('I am ', os.getpid())
rand_num = random.randint(0, 20)

def foo():
    print('I am {}, rand_num is {}'.format(os.getpid(), rand_num))   # 子进程的 rand_num


print('I am {}, rand_num is {}'.format(os.getpid(), rand_num))  # 父进程的 rand_num
p = Process(target=foo)
p.start()
p.join()

'''
I am  3811
I am 3811, rand_num is 17
I am 3841, rand_num is 17
'''
'''
感觉好像靠谱了
'''

用 fork 呢?

# coding : utf-8

import os
import random

print('I am ', os.getpid())
rand_num = random.randint(0, 20)

ret = os.fork()

if ret==0:
    print('child pid is {}, rand_num is {}'.format(os.getpid(), rand_num))
else:
    print('parent pid is {}, rand_num is {}'.format(os.getpid(), rand_num))

'''
I am  4054
parent pid is 4054, rand_num is 12
child pid is 4084, rand_num is 12
'''
'''
真好
'''

但是有一个问题就是 multiprocessing 在 Linux 系统上和 windows 系统下表现不一致, Linux 系统下 Python 用 fork 实现了多进程?

请问学习多进程有什么好的资料吗?想多学一点这方面的知识,今天搞的有点懵圈

2111 次点击
所在节点    Python
8 条回复
polythene
2017-01-05 22:19:20 +08:00
这次修坑的过程就是最好的学习资料~
https://docs.python.org/2/library/multiprocessing.html#windows 官方文档也写了 multiprocessing 在 Windows 平台的不一致性。
neoblackcap
2017-01-05 23:11:39 +08:00
Windows 下没有 fork ,表现不一样不是很正常的吗?而且 Windows 的进程模型跟 linux 也不一样
Allianzcortex
2017-01-05 23:33:33 +08:00
posix 线程和 Windows 线程是不一样的底层实现机制嘛
wwqgtxx
2017-01-06 07:52:52 +08:00
python2 和 3 的官方文档都写了, multiprocessing 在 wun 上的实现是开启一个新进程,而在 posix 环境下默认使用 fork 方式。当然这个启动方式是可以更改的,可以在初始化 Process 的时候指定启动方式( win 下 fork 不可用而已)
wisefree
2017-01-06 08:22:21 +08:00
@polythene 恩,当初没仔细看文档,现在来好好看看。以前都是以为底层实现机制都被封装,一样的代码能够得到一样的结果,这才是跨平台嘛。。看来还是书读少了
wisefree
2017-01-06 08:24:13 +08:00
@neoblackcap 。没有太了解进程模型,一直以为一样的 python 代码会在不同的平台得到一样的结果,所以这次增加了一点经验。
wisefree
2017-01-06 08:24:47 +08:00
@Allianzcortex 厉害呀,我并不了解底层实现机制
wisefree
2017-01-06 08:25:20 +08:00
@wwqgtxx 恩恩,才去看文档,确实写了。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/332517

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX