V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
wisefree
V2EX  ›  Python

multiprocessing 与平台有关

  •  
  •   wisefree · 2017-01-05 21:34:43 +08:00 · 2096 次点击
    这是一个创建于 2681 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天遇到了一个很让人费解的问题。问题的起因是没有把多进程程序写在 __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 实现了多进程?

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

    8 条回复    2017-01-06 08:25:20 +08:00
    polythene
        1
    polythene  
       2017-01-05 22:19:20 +08:00   ❤️ 1
    这次修坑的过程就是最好的学习资料~
    https://docs.python.org/2/library/multiprocessing.html#windows 官方文档也写了 multiprocessing 在 Windows 平台的不一致性。
    neoblackcap
        2
    neoblackcap  
       2017-01-05 23:11:39 +08:00   ❤️ 1
    Windows 下没有 fork ,表现不一样不是很正常的吗?而且 Windows 的进程模型跟 linux 也不一样
    Allianzcortex
        3
    Allianzcortex  
       2017-01-05 23:33:33 +08:00   ❤️ 1
    posix 线程和 Windows 线程是不一样的底层实现机制嘛
    wwqgtxx
        4
    wwqgtxx  
       2017-01-06 07:52:52 +08:00 via iPhone   ❤️ 1
    python2 和 3 的官方文档都写了, multiprocessing 在 wun 上的实现是开启一个新进程,而在 posix 环境下默认使用 fork 方式。当然这个启动方式是可以更改的,可以在初始化 Process 的时候指定启动方式( win 下 fork 不可用而已)
    wisefree
        5
    wisefree  
    OP
       2017-01-06 08:22:21 +08:00
    @polythene 恩,当初没仔细看文档,现在来好好看看。以前都是以为底层实现机制都被封装,一样的代码能够得到一样的结果,这才是跨平台嘛。。看来还是书读少了
    wisefree
        6
    wisefree  
    OP
       2017-01-06 08:24:13 +08:00
    @neoblackcap 。没有太了解进程模型,一直以为一样的 python 代码会在不同的平台得到一样的结果,所以这次增加了一点经验。
    wisefree
        7
    wisefree  
    OP
       2017-01-06 08:24:47 +08:00
    @Allianzcortex 厉害呀,我并不了解底层实现机制
    wisefree
        8
    wisefree  
    OP
       2017-01-06 08:25:20 +08:00
    @wwqgtxx 恩恩,才去看文档,确实写了。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5367 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 01:14 · PVG 09:14 · LAX 18:14 · JFK 21:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.