
下面这段代码在 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() 1 ysc3839 2019-01-06 18:07:25 +08:00 via Android Windows 不支持 fork 吧?没把变量拷贝到别的进程。 |
4 smelond OP @ysc3839 咋个初始化呢,是这样么? 但是这样之后程序一秒运行完成,没有执行里面的操作 ``` python global SEM SEM = threading.Semaphore(int(args.THREAD)) ``` |
6 lihongjie0209 2019-01-06 18:58:07 +08:00 你要把这两个变量放到全局变量中去 |
7 smelond OP @ysc3839 不好意思,感谢你的回复,感觉可能惹你生气了,我对 Python 也不是太熟练,听到你说了在 test1 里面初始化 SEM,我想了一下,想到了我可以先将: sem = int(args.THREAD) time_out = int(args.OVERTIME) 放到 main 函数里面,然后通过传参方式,从 mian-> test1->test 最后直接在 test 里面写入 with threading.Semaphore(sem): 然后可以成功的运行,感谢你的回复 |
8 smelond OP @lihongjie0209 放到全局变量里面 不管怎么样,test 函数就是不识别 |
10 cgsv 2019-01-06 20:17:46 +08:00 |
11 Vegetable 2019-01-06 20:49:17 +08:00 via Android 一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。 |
12 JCZ2MkKb5S8ZX9pq 2019-01-06 20:58:24 +08:00 多进程好像可以设一个 value 作为公用的变量,类似锁吧。 多线程以前试过,但没什么印象了。反正最后用多进程了。 |
13 xiangace 2019-01-07 01:08:18 +08:00 1. 多线程实际上还是利用单核, 直接用多进程. 2. Python 在共享全局变量这块做的不太好, 多线程场景可以查询下 thread local 相关的资料. 多进程考虑 multiprocessing 的 value 机制, multiprocessing 支持一个 daemon 进程维护这组变量, 多进程通过 IPC |
14 xiangace 2019-01-07 01:14:33 +08:00 接上一跳评论,理解错题意了, win 下的机制比较诡异. |
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 |
16 a226679594 2019-01-07 08:33:10 +08:00 把这两个变量放到全局变量中去 |
17 arrow8899 2019-01-07 09:13:13 +08:00 多进程是不能共享变量的,可以用共享内存试试 |
18 arrow8899 2019-01-07 09:24:36 +08:00 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 2019-01-07 10:08:34 +08:00 在函数里引用了 既不是参数,又不是本地定义 的变量 这是一种很典型的错误 |
20 qcts33 2019-01-07 11:07:31 +08:00 显试的传递一下不行吗…… |
21 a226679594 2019-01-09 09:22:51 +08:00 一般来说,可以认为 Windows 不能直接使用 multiprocessing,也就是不支持多进程。 |
22 old18 2019-01-10 11:10:52 +08:00 多进程不共享全局变量, 把 SEM 存放在消息队列里,就应该好了... |