首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
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
V2EX  ›  Python

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

  •  
  •   smelond · 46 天前 · 1484 次点击
    这是一个创建于 46 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面这段代码在 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
        1
    ysc3839   46 天前 via Android
    Windows 不支持 fork 吧?没把变量拷贝到别的进程。
        2
    smelond   46 天前
    @ysc3839 请问这个还有办法解决吗
        3
    ysc3839   46 天前 via Android   ♥ 1
    @smelond 在 test1 中初始化 SEM。
        4
    smelond   46 天前
    @ysc3839 咋个初始化呢,是这样么? 但是这样之后程序一秒运行完成,没有执行里面的操作
    ``` python

    global SEM
    SEM = threading.Semaphore(int(args.THREAD))
    ```
        5
    ysc3839   46 天前 via Android
    @smelond 那我也不知道了……是我不懂 Python。
        6
    lihongjie0209   46 天前
    你要把这两个变量放到全局变量中去
        7
    smelond   46 天前
    @ysc3839 不好意思,感谢你的回复,感觉可能惹你生气了,我对 Python 也不是太熟练,听到你说了在 test1 里面初始化 SEM,我想了一下,想到了我可以先将:
    sem = int(args.THREAD)
    time_out = int(args.OVERTIME)
    放到 main 函数里面,然后通过传参方式,从 mian-> test1->test 最后直接在 test 里面写入
    with threading.Semaphore(sem): 然后可以成功的运行,感谢你的回复
        8
    smelond   46 天前
    @lihongjie0209 放到全局变量里面 不管怎么样,test 函数就是不识别
        9
    ysc3839   46 天前 via Android
    @smelond 我没生气啊,我真的不懂啊……
    我从来没用过 multiprocess,前面只是随口说说以为可以解决问题,但解决不了我就真的不懂了。
        11
    Vegetable   46 天前 via Android
    一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。
        12
    JCZ2MkKb5S8ZX9pq   46 天前
    多进程好像可以设一个 value 作为公用的变量,类似锁吧。
    多线程以前试过,但没什么印象了。反正最后用多进程了。
        13
    xiangace   46 天前
    1. 多线程实际上还是利用单核, 直接用多进程.
    2. Python 在共享全局变量这块做的不太好, 多线程场景可以查询下 thread local 相关的资料.
    多进程考虑 multiprocessing 的 value 机制, multiprocessing 支持一个 daemon 进程维护这组变量, 多进程通过 IPC
        14
    xiangace   46 天前
    接上一跳评论,理解错题意了, win 下的机制比较诡异.
        15
    lrxiao   46 天前
    multi process 本身就不能假设同一个东西会 share between processes...
    然后就是 message-passing or shared memory
    https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Value
        16
    a226679594   46 天前
    把这两个变量放到全局变量中去
        17
    arrow8899   46 天前
    多进程是不能共享变量的,可以用共享内存试试
        18
    arrow8899   46 天前   ♥ 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())
    ```
        19
    julyclyde   46 天前
    在函数里引用了
    既不是参数,又不是本地定义
    的变量
    这是一种很典型的错误
        20
    qcts33   46 天前
    显试的传递一下不行吗……
        21
    a226679594   44 天前
    一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。
        22
    old18   43 天前
    多进程不共享全局变量, 把 SEM 存放在消息队列里,就应该好了...
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3840 人在线   最高记录 4385   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 25ms · UTC 07:45 · PVG 15:45 · LAX 23:45 · JFK 02:45
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1