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
smelond
V2EX    Python

Python 关于多线程和多进程同时共用问题

  •  
  •   smelond 2019-01-06 17:57:07 +08:00 5296 次点击
    这是一个创建于 2523 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面这段代码在 windows 下运行就报错 NameError: name 'SEM' is not defined

    在 windows7 windows10 测试 报错

    在 Mac Linux 下测试 能正常运行

    如果我在代码的最上面给 SEM 和 TIME_OUT 赋值后,就能正常运行

    但是我需要用户加参数将值带进去,而不是事先定义好,所以只能放到 argparse 里面。我现在很疑惑,这个问题能解决吗?

    时间过了两天了,依旧没有解决这个问题,希望小伙伴们能和我一起讨论一下怎么回事,谢谢!

    # /usr/bin/env python # _*_ coding:utf-8 _*_ import argparse, datetime, time import threading from multiprocessing import Pool def test(i): with SEM: print(i) time.sleep(TIME_OUT) def test1(c): threads = [] for i in range(int(200)): t = threading.Thread(target=test, args=(i,)) t.start() threads.append(t) for t in threads: t.join() def main(): start_time = time.time() print(datetime.datetime.now().strftime('Start Time: %m/%d/%Y %H:%M:%S')) p = Pool(int(args.PROCESS)) for i in range(10): p.apply_async(test1, args=(i,)) p.close() p.join() print(datetime.datetime.now().strftime('Complete time: %m/%d/%Y %H:%M:%S')) print("Total time:%s" % (time.time() - start_time)) if __name__ == '__main__': parser = argparse.ArgumentParser(description='test') parser.add_argument('-m', dest='PROCESS', type=int, help='多进程数量,默认 5', default=5) parser.add_argument('-t', dest='THREAD', type=int, help='多线程数量,默认 20', default=20) parser.add_argument('-o', dest='OVERTIME', type=int, help='超时时间 默认 2', default=2) args = parser.parse_args() SEM = threading.Semaphore(int(args.THREAD)) TIME_OUT = int(args.OVERTIME) main() 
    22 条回复    2019-01-10 11:10:52 +08:00
    ysc3839
        1
    ysc3839  
       2019-01-06 18:07:25 +08:00 via Android
    Windows 不支持 fork 吧?没把变量拷贝到别的进程。
    smelond
        2
    smelond  
    OP
       2019-01-06 18:26:06 +08:00
    @ysc3839 请问这个还有办法解决吗
    ysc3839
        3
    ysc3839  
       2019-01-06 18:29:04 +08:00 via Android   1
    @smelond 在 test1 中初始化 SEM。
    smelond
        4
    smelond  
    OP
       2019-01-06 18:37:39 +08:00
    @ysc3839 咋个初始化呢,是这样么? 但是这样之后程序一秒运行完成,没有执行里面的操作
    ``` python

    global SEM
    SEM = threading.Semaphore(int(args.THREAD))
    ```
    ysc3839
        5
    ysc3839  
       2019-01-06 18:43:52 +08:00 via Android
    @smelond 那我也不知道了……是我不懂 Python。
    lihongjie0209
        6
    lihongjie0209  
       2019-01-06 18:58:07 +08:00
    你要把这两个变量放到全局变量中去
    smelond
        7
    smelond  
    OP
       2019-01-06 19:04:51 +08:00
    @ysc3839 不好意思,感谢你的回复,感觉可能惹你生气了,我对 Python 也不是太熟练,听到你说了在 test1 里面初始化 SEM,我想了一下,想到了我可以先将:
    sem = int(args.THREAD)
    time_out = int(args.OVERTIME)
    放到 main 函数里面,然后通过传参方式,从 mian-> test1->test 最后直接在 test 里面写入
    with threading.Semaphore(sem): 然后可以成功的运行,感谢你的回复
    smelond
        8
    smelond  
    OP
       2019-01-06 19:07:00 +08:00
    @lihongjie0209 放到全局变量里面 不管怎么样,test 函数就是不识别
        9
    ysc3839  
       2019-01-06 19:56:52 +08:00 via Android
    @smelond 我没生气啊,我真的不懂啊……
    我从来没用过 multiprocess,前面只是随口说说以为可以解决问题,但解决不了我就真的不懂了。
    ysc3839
    Vegetable
        11
    Vegetable  
       2019-01-06 20:49:17 +08:00 via Android
    一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。
    JCZ2MkKb5S8ZX9pq
        12
    JCZ2MkKb5S8ZX9pq  
       2019-01-06 20:58:24 +08:00
    多进程好像可以设一个 value 作为公用的变量,类似锁吧。
    多线程以前试过,但没什么印象了。反正最后用多进程了。
    xiangace
        13
    xiangace  
       2019-01-07 01:08:18 +08:00
    1. 多线程实际上还是利用单核, 直接用多进程.
    2. Python 在共享全局变量这块做的不太好, 多线程场景可以查询下 thread local 相关的资料.
    多进程考虑 multiprocessing 的 value 机制, multiprocessing 支持一个 daemon 进程维护这组变量, 多进程通过 IPC
    xiangace
        14
    xiangace  
       2019-01-07 01:14:33 +08:00
    接上一跳评论,理解错题意了, win 下的机制比较诡异.
    lrxiao
        15
    lrxiao  
       2019-01-07 01:14:34 +08:00
    multi process 本身就不能假设同一个东西会 share between processes...
    然后就是 message-passing or shared memory
    https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Value
    a226679594
        16
    a226679594  
       2019-01-07 08:33:10 +08:00
    把这两个变量放到全局变量中去
    arrow8899
        17
    arrow8899  
       2019-01-07 09:13:13 +08:00
    多进程是不能共享变量的,可以用共享内存试试
    arrow8899
        18
    arrow8899  
       2019-01-07 09:24:36 +08:00   1
    shared_mem = manager.dict() 这一句就是添加一个共享内存,可以在多进程之间使用
    ```
    # /usr/bin/env python
    # _*_ coding:utf-8 _*_


    import argparse, datetime, time
    import threading
    import multiprocessing


    def test(i):
    with SEM:
    print(i)
    time.sleep(TIME_OUT)


    def test1(c, data):
    global SEM
    global TIME_OUT
    SEM = data['SEM']
    TIME_OUT = datda['TIME_OUT']

    threads = []
    for i in range(200):
    t = threading.Thread(target=test, args=(i,))
    t.start()
    threads.append(t)
    for t in threads:
    t.join()


    def main(args):
    start_time = time.time()
    print(datetime.datetime.now().strftime('Start Time: %m/%d/%Y %H:%M:%S'))
    manager = multiprocessing.Manager()
    p = multiprocessing.Pool(int(args.PROCESS))

    shared_mem = manager.dict()
    shared_mem['SEM'] = threading.Semaphore(int(args.THREAD))
    shared_mem['TIME_OUT'] = int(args.OVERTIME)

    for i in range(10):
    p.apply_async(test1, args=(i, shared_mem))
    p.close()
    p.join()
    print(datetime.datetime.now().strftime('Complete time: %m/%d/%Y %H:%M:%S'))
    print("Total time:%s" % (time.time() - start_time))


    if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='test')
    parser.add_argument('-m', dest='PROCESS', type=int, help='多进程数量,默认 5', default=5)
    parser.add_argument('-t', dest='THREAD', type=int, help='多线程数量,默认 20', default=20)
    parser.add_argument('-o', dest='OVERTIME', type=int, help='超时时间 默认 2', default=2)
    main(parser.parse_args())
    ```
    julyclyde
        19
    julyclyde  
       2019-01-07 10:08:34 +08:00
    在函数里引用了
    既不是参数,又不是本地定义
    的变量
    这是一种很典型的错误
    qcts33
        20
    qcts33  
       2019-01-07 11:07:31 +08:00
    显试的传递一下不行吗……
    a226679594
        21
    a226679594  
       2019-01-09 09:22:51 +08:00
    一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。
    old18
        22
    old18  
       2019-01-10 11:10:52 +08:00
    多进程不共享全局变量, 把 SEM 存放在消息队列里,就应该好了...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1027 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 22:51 PVG 06:51 LAX 14:51 JFK 17:51
    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