python多进程中实现进程间数据传递和通信
进程与线程一个不同点在于,线程之可以共享一块内存空间,而进程的内存空间是互相独立的,进程之间要传递数据需要依靠“中间人”,而Queue类能够提供这个功能
下面这个程序使用的是普通queue模块实例化的队列,通过父进程向子进程传递了一个普通队列,并在run
函数中向队列添加了一个列表元素,用于检验父进程能否get
到这个元素.
#Downtiser
import multiprocessing, queue
def run(q):
q.put(['a', 1, 'bcd'])
if __name__ == '__main__':
q1 = queue.Queue() #实例化普通队列
p = multiprocessing.Process(target=run, args=(q1,))
p.start()
p.join()
print(q1.get())
结果抛出了一个异常>>>TypeError: can't pickle _thread.lock objects
于是使用多进程Queue
做同样操作
#Downtiser
import multiprocessing, queue
def run(q):
q.put(['a', 1, 'bcd'])
if __name__ == '__main__':
q1 = multiprocessing.Queue() #实例化多进程队列
p = multiprocessing.Process(target=run, args=(q1,))
p.start()
p.join()
print(q1.get())
此时主进程能正常get
到队列中的元素>>>['a', 1, 'bcd']
难道是多进程队列实现了不同进程之间共享数据? 于是修改程序,打印队列本身,如果是共享的话,在主进程和子进程里打印的队列应该拥有同一块内存地址。程序修改如下:
#Downtiser
import multiprocessing, queue
def run(q):
print('这是子进程的队列>>>',q)
q.put(['a', 1, 'bcd'])
if __name__ == '__main__':
q1 = multiprocessing.Queue() #实例化多进程队列
print('这是主进程的队列>>>',q1)
p = multiprocessing.Process(target=run, args=(q1,))
p.start()
p.join()
print(q1.get())
得结果如下:
这是主进程的队列>>> <multiprocessing.queues.Queue object at 0x04A3EC50>
这是子进程的队列>>> <multiprocessing.queues.Queue object at 0x04CEDC30>
['a', 1, 'bcd']
可以发现两个队列的内存地址并不同,所以两个进程实际上并没有共享一个队列,而是子进程复制了一份主进程的队列。查阅资料了解到,多进程队列实际上是将原队列先传递到一个"中间人"处,通过pickle序列化,反序列化,中间人将队列信息传递到另一个进程处,另一个进程将队列修改后,再传递给中间人,其他进程调用时就会发现队列被修改了,表面上达到了共享数据的效果
多进程队列实现了进程间数据传递,而多进程管道,可实现进程间通信,类似于socket
代码实现如下
#Downtiser
import multiprocessing
def run(conn):
conn.send("这是子进程")
print(conn.recv())
if __name__ == '__main__':
conn_parent, conn_children = multiprocessing.Pipe() #创建管道实例,建立两个连接,类似于socket
p = multiprocessing.Process(target=run, args=(conn_children,)) #创建子进程,并将管道子端传入
p.start()
print(conn_parent.recv())
conn_parent.send('我是父进程')
p.join()
结果:
这是子进程
我是父进程
用Manager
实现数据共享
#Downtiser
import multiprocessing, os
def run(dic, lis):
dic['pid'] = os.getpid()
lis.append(os.getpid())
print('---子进程>>>', hex(id(dic)), hex(id(lis)))
print(lis)
if __name__ == '__main__':
with multiprocessing.Manager() as manager: #生成Manager实例,该实例可用于实现进程间的数据共享
dic = manager.dict() #通过manager生成一个可共享的字典
lis = manager.list() #同上
print('---主进程>>>',hex(id(dic)), hex(id(lis))) #16进制返回变量的内存地址
p_list = []
for i in range(10):
p = multiprocessing.Process(target=run, args=(dic, lis))
p_list.append(p)
p.start()
for p in p_list:
p.join()
print(dic)
结果:
---主进程>>> 0x58f89d0 0x58130f0
---子进程>>> 0x5491af0 0x5494890
[3520]
---子进程>>> 0x58a1510 0x58a4730
[3520, 9748]
---子进程>>> 0x5281ad0 0x5284870
[3520, 9748, 6560]
---子进程>>> 0x5771ad0 0x5774870
[3520, 9748, 6560, 15732]
---子进程>>> 0x54a1ab0 0x54a4850
[3520, 9748, 6560, 15732, 13140]
---子进程>>> 0x5731b10 0x57348b0
[3520, 9748, 6560, 15732, 13140, 13136]
---子进程>>> 0x5911af0 0x5914890
[3520, 9748, 6560, 15732, 13140, 13136, 16176]
---子进程>>> 0x5b21ad0 0x5b24870
[3520, 9748, 6560, 15732, 13140, 13136, 16176, 11624]
---子进程>>> 0x5801b10 0x58048b0
[3520, 9748, 6560, 15732, 13140, 13136, 16176, 11624, 13228]
---子进程>>> 0x5aa1af0 0x5aa4890
[3520, 9748, 6560, 15732, 13140, 13136, 16176, 11624, 13228, 4716]
{'pid': 4716
用Manager还可支持其他多种类型的数据,如元组,队列,信号量,进程锁等
相关文章
- Django基本命令
Django基本命令 打开linux终端直接在终端中输入以下命令即可。 新建一个django project 命令:django-admin.py startproject project-nam
- 17个新手常见Python运行时错误
17个新手常见Python运行时错误 当初学 Python 时,想要弄懂 Python 的错误信息的含义可能有点复杂。这里列出了常见的的一些让你程序 crash 的运行时错误。 当初学 Python
- Python+SQLite真的有用吗?
SQLite是个很简单的数据库,一个文件就可以搞定,存储上千万行的数据也没问题,图形界面程序有很多,管理很方便,用Python可以编程操作,也很简单,一切都似乎很完美。 我导入了几千万行的数据进SQL
- os各种各样的操作系统接口
这个模块提供了一种使用操作系统相关功能的移动方式。如果您只想读取或写入一个文件,请查看open(),如果您想要操作路径,请参见操作os.path模块,如果您想要读取命令行上所有文件中的所有行,请参阅f
- 通过webpy和nginx-with-fastcgi搭建web.py
这一节讲解的是如何使用Nginx和FastCGI搭建Web.py应用 环境依赖的软件包 Nginx 0.8.* or 0.7.* (需要包含fastcgi和rewrite模块)。 Webpy 0.3
随机推荐
- Django基本命令
Django基本命令 打开linux终端直接在终端中输入以下命令即可。 新建一个django project 命令:django-admin.py startproject project-nam
- 17个新手常见Python运行时错误
17个新手常见Python运行时错误 当初学 Python 时,想要弄懂 Python 的错误信息的含义可能有点复杂。这里列出了常见的的一些让你程序 crash 的运行时错误。 当初学 Python
- Python+SQLite真的有用吗?
SQLite是个很简单的数据库,一个文件就可以搞定,存储上千万行的数据也没问题,图形界面程序有很多,管理很方便,用Python可以编程操作,也很简单,一切都似乎很完美。 我导入了几千万行的数据进SQL
- os各种各样的操作系统接口
这个模块提供了一种使用操作系统相关功能的移动方式。如果您只想读取或写入一个文件,请查看open(),如果您想要操作路径,请参见操作os.path模块,如果您想要读取命令行上所有文件中的所有行,请参阅f
- 通过webpy和nginx-with-fastcgi搭建web.py
这一节讲解的是如何使用Nginx和FastCGI搭建Web.py应用 环境依赖的软件包 Nginx 0.8.* or 0.7.* (需要包含fastcgi和rewrite模块)。 Webpy 0.3