day10 -进程间数据的交换
一、概述
我们知道不同进程之间内存是不能共享的,要想实现进程间的数据通讯,怎么搞呢,请看下面,
类似,中间需要有一个翻译,例如:一个英国人,一个中国人,需要有一个会说中文,又会说英语的人做翻译。
二、前戏
之前我们说了queue,这个是线程queue,它的主要目的是两个线程之间的数据,一个是生产者,一个是消费者的模型,而且你必须是线程。只能在这个主线程内的其他线程访问,出了这个进程,你就不能被访问了。
2.1、进程访问queue
1 from multiprocessing import Process 2 import queue 3 4 def f(pq): 5 q.put("niubi") 6 7 if __name__ == "__main__": 8 q=queue.Queue() 9 p=Process(target=f,args=(q,)) 10 p.start() 11 print(q.get()) 12 p.join() 13 14 ===出错信息 15 D:\51cto\venv\Scripts\python.exe "D:/51cto/day 10/tq&pq.py" 16 Traceback (most recent call last): 17 File "D:/51cto/day 10/tq&pq.py", line 11, in <module> 18 p.start() 19 File "d:\ProgramData\Anaconda3\Lib\multiprocessing\process.py", line 105, in start 20 self._popen = self._Popen(self) 21 File "d:\ProgramData\Anaconda3\Lib\multiprocessing\context.py", line 223, in _Popen 22 return _default_context.get_context().Process._Popen(process_obj) 23 File "d:\ProgramData\Anaconda3\Lib\multiprocessing\context.py", line 322, in _Popen 24 return Popen(process_obj) 25 File "d:\ProgramData\Anaconda3\Lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__ 26 reduction.dump(process_obj, to_child) 27 File "d:\ProgramData\Anaconda3\Lib\multiprocessing\reduction.py", line 60, in dump 28 ForkingPickler(file, protocol).dump(obj) 29 TypeError: can't pickle _thread.lock objects
2.2、线程Q
1 import threading,queue 2 3 4 def f(tt): 5 q.put("niubi") 6 7 if __name__ == '__main__': 8 q=queue.Queue() 9 p=threading.Thread(target=f,args=(q,)) 10 p.start() 11 print(q.get()) 12 p.join()
很明显是可以的。由此得出,线程queue传给子进程是不可以的,你以为传给它了,其实传不了,如果你想传的话,必须是进程Queue。
三、进程Q,进程间的通讯
说明:这个Queue是用于进程之间的数据通信,使用方法跟threading里的queue差不多。
1 from multiprocessing import Process 2 from multiprocessing import Queue 3 4 def f(pq): 5 pq.put("niubi") 6 7 if __name__ == '__main__': 8 9 q = Queue() 10 p=Process(target=f,args=(q,)) 11 p.start() 12 print(q.get()) 13 p.join()
提问:父进程的q是怎么传给子进程的?
父进程相当于克隆一个Q,把自己的Q克隆了一份交给子进程,子进程这个时候往Q里面放了一份数据,然后父进程又能实际的获取到。但是你克隆了一份是不是就和父进程没有关系了,为什么还能联系在一起呢?但是实际上:等于这两个Q里面的数据又把它序列化了,序列化到一个中间的地方,类似于翻译,然后反序列化给这个父进程这边来了,其实这两个Q就是通过pickle来序列化的,不是一个真正的Q。
小结:
两个线程之间可以修改一个数据,不加锁,可能就会出错。现在进程中的Queue,是实现了数据的传递,不是在修改同一份数据,只是实现一个进程的数据传给了另外一个进程。

浙公网安备 33010602011771号