对 Python 里多进程池用法有点迷茫 - V2EX
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
youthfire

对 Python 里多进程池用法有点迷茫

  •  
  •   youthfire 2020 年 8 月 6 日 3879 次点击
    这是一个创建于 2087 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大致看了下多线程和多进程的关系 多线程里同名变量写起来容易冲突麻烦,所以就用了多进程.这个多进程用起来有点迷茫 (运行环境是 Mac)

    我多进程的写发如下

    p = Pool(processes=6) p.apply_async(过程名,参数) p.close() p.join() 
    • 迷惑一:只要程序前不加 if name == 'main':,根本无法跑起来.报各种错误
    • 迷惑二:程序全都跑完了,要卡很久才结束(命令都执行完了,就是不跳回待输入命令行状态)
    • 迷惑三:是不是核数应该填最大值?(比如我是 8),还是说一般有必要保留冗余呢?
    22 条回复    2023-02-01 12:09:57 +08:00
    yngzij
        1
    yngzij  
       2020 年 8 月 6 日
    由于 Windows 没有 fork,因此多处理模块将启动一个新的 Python 进程并导入调用模块 没有 if name == 'main' 会重复创建副本。
    youthfire
        2
    youthfire  
    OP
       2020 年 8 月 6 日 via iPhone
    @yngzij #1 我的运行环境也是 Mac 平台,你的意思是不管运行环境如何,Python 就是这样设计的?
    XiaoxiaoPu
        3
    XiaoxiaoPu  
       2020 年 8 月 6 日
    @youthfire Python 版本是什么?最新的 Python 多进程有三种模式,spawn 、fork 、forkserver,不同模式行为是不一样的。Python 3.8 在 macOS 下默认模式为 spawn,子进程是一个全新的解释器。
    crella
        4
    crella  
       2020 年 8 月 6 日 via Android
    找个类把同名变量包起来可以吗?
    lithbitren
        5
    lithbitren  
       2020 年 8 月 6 日   1
    核数不填的时候默认最大,卡很久结束没碰到过,几个进程应该时几十到几百毫秒内结束。
    if name == 'main'必须加,不然会重复创建对象副本,每个进程的对象都是单独运算的。
    多进程有些函数需要些全局 def,反而是副本才能正常调用,用局部或 lambda 可能会 pickle 失败,其实正常写 py 不管啥脚本都建议加 main 的判断块,就跟其他语言包进 main 函数里面一样
    neoblackcap
        6
    neoblackcap  
       2020 年 8 月 6 日
    @lithbitren 重复创建对象副本是什么意思?
    youthfire
        7
    youthfire  
    OP
       2020 年 8 月 6 日 via iPhone
    @XiaoxiaoPu #3 谢谢分享,我用的 3.8.5 。
    youthfire
        8
    youthfire  
    OP
       2020 年 8 月 6 日 via iPhone
    @lithbitren #5 谢谢指点。我也就放了 12 个简单的 web 抓取数据进程,就是都跑完了,各进程都输出结果了,然后不动了,过很久最终结束。可能的话,我晚点放完整代码上来。
    XiaoxiaoPu
        9
    XiaoxiaoPu  
       2020 年 8 月 6 日
    @youthfire 抓取数据的话,简单点可以用多线程的,坑少一点
    imn1
        10
    imn1  
       2020 年 8 月 6 日
    1.不需要 main,但启动要在顶级,我也说不清楚那些术语
    举例,在根建一个 fun,里面写 multiprocess,然后在其他地方传参过去调用这个 fun
    multiprocess 写在类方法里面,运行会报错,但按上面的写法,类方法里面调用这个 fun 则可以正常运行
    2.不晓得,是不是 IO 太多?
    3.processes 这个貌似只是进程数吧,chrome 可以起几十个进程呢,当然多了也是问题

    我只是知其然,不知其所以然,会写会抄,但搞不清状况,说错了勿怪
    非 Mac 用户
    renmu123
        11
    renmu123  
       2020 年 8 月 6 日 via Android
    如果是 io 密集型推荐使用多线程,会比多进程快那么一丢丢,多线程也是有池的,在多进程模块里,你翻一下文档
    XiaoxiaoPu
        12
    XiaoxiaoPu  
       2020 年 8 月 6 日
    spawn 、forkserver 模式下,进程的 run 函数和参数需要进程间通信来传递,这个过程会用 pickle 来序列化、反序列化,所以 run 函数和参数会受 pickle 的限制,pickle 支持如下数据类型

    * None, True, and False
    * integers, floating point numbers, complex numbers
    * strings, bytes, bytearrays
    * tuples, lists, sets, and dictionaries containing only picklable objects
    * functions defined at the top level of a module (using def, not lambda)
    * built-in functions defined at the top level of a module
    * classes that are defined at the top level of a module
    * instances of such classes whose __dict__ or the result of calling __getstate__() is picklable (see section Pickling Class Instances for details).
    XiaoxiaoPu
        13
    XiaoxiaoPu  
       2020 年 8 月 6 日
    「程序前不加 if name == 'main'」这种情况下,你的 python 文件就没法被 import,因为 import 隐含了运行代码,死循环了
    lithbitren
        14
    lithbitren  
       2020 年 8 月 6 日
    抓数据还是建议多线程或协程,多进程开几个没啥体感,开几十几百个就知道什么叫肉眼可见的慢了,协程线程一般个人项目开多少都没啥体感,而且协程线程数据可以直接共享,不用像多进程那样考虑 pickle 的问题。
    计算密集也不一定多进程,单核睿频一般能到 1.5-1.8 倍的处理速度,个人机全跑满实际也就多个 3-6 倍,但要考虑的东西复杂得多,进程间的各种传值操作也有不小开销,不是计算特别耗时的项目,还不如直接单进程跑线程协程。
    youthfire
        15
    youthfire  
    OP
       2020 年 8 月 6 日
    @imn1 @renmu123 @XiaoxiaoPu 感谢分享心得和理解
    @lithbitren 说得很量化,我会试试线程或协程,谢谢
    Te11UA
        16
    Te11UA  
       2020 年 8 月 6 日
    @lithbitren 那这样的话,单进程不就利用不了多核麽?
    lithbitren
        17
    lithbitren  
       2020 年 8 月 6 日
    @Te11UA 多进程麻烦啊,比如抓数据一条几秒抓回来,处理数据就几到几十毫秒,需要并行处理的机会也不一定太高,个人电脑多核计算对这几十毫秒意义不大,不如直接单进程省事,想用也可以,只是不推荐而已。
    youthfire
        18
    youthfire  
    OP
       2020 年 8 月 6 日
    晚上特地去试验了下协程,用的 gevent.joinall([gevent.spawn(函数)若干]),整体感觉就跟没用一样,比多进程慢很多. 准备用一下多线程
    lithbitren
        19
    lithbitren  
       2020 年 8 月 7 日
    @youthfire 现在 Python 讲的协程基本都是官办协程了,不过 gevent 爬虫可以直接用 grequests,也不费事。
    wuwukai007
        20
    wuwukai007  
       2020 年 8 月 7 日 via Android
    @lithbitren grequests 挺占内存的
    youthfire
        21
    youthfire  
    OP
       2020 年 8 月 7 日 via iPhone
    @lithbitren #19 改用了多线程池后发现效果确实不错,速度甚至更快,也没有多进程池那最后卡顿了(虽然不明白卡顿是什么原因)
    phoulx
        22
    phoulx  
       2023 年 2 月 1 日 via iPhone
    卡顿是因为 apply_async 返回 AsyncResult 对象,但是运行结果实际在 join()时才执行得到。AsyncResult 可以手动 get()结果,也可以加上 callback 参数来指定回调动作。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1546 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 75ms UTC 16:48 PVG 00:48 LAX 09:48 JFK 12:48
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86