多线程给我们的感觉

  1.因为GIL的存在,一个进程的多线程同一时刻只能进去一个,感觉是假的并发

  2.只适合I/O密集型的任务

  3.针对计算密集型,就挂了(变成串行了)

在python中想要充分利用多核cpu的优势,就可用多进程这个技术---multiprocessing

multiprocessing是多进程的一个管理包。包含 Process、Queue、Pipe、Lock等组件。与thread类似

  该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。

但在使用这些共享API的时候,我们要注意以下几点:

  • 在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。
  • multiprocessing提供了threading包中没有的IPC(比如Pipe和Queue),效率上更高。应优先考虑Pipe和Queue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)。
  • 多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

简单的例子:

from multiprocessing import Process
import os
def info(name):
print(name)
print(os.getppid())#在主进程运行的是的是这个是pychar的pid
print(os.getpid()) if __name__ == "__main__":
info("main")
p=Process(target=info,args=("bob",))
p.start()
p.join()

进程之间通讯

1. Queue()  注意这个不同于进程queue。  每个进程之间使用pickle序列化实现

2. Pipe()

queue代码:注意q要当参数 传递给函数,不然无法使用。因为进程之间数据默认不共享的。

from multiprocessing import Process, Queue

def f(q,n):
q.put([42, n, 'hello']) if __name__ == '__main__':
q = Queue()
p_list=[]
for i in range(3):
p = Process(target=f, args=(q,i))
p_list.append(p)
p.start()
print(q.get())
print(q.get())
print(q.get())
for i in p_list:
i.join()

Pipe代码

from multiprocessing import Process, Pipe

def f(conn):
conn.send([42, None, 'hello'])
conn.close() if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print(parent_conn.recv()) # prints "[42, None, 'hello']"
p.join()

进程之间数据共享:Manager组件

from multiprocessing import Process, Manager

def f(d, l,n):
d[n] = ''
d[''] = 2
d[0.25] = None
l.append(n)
print(l) if __name__ == '__main__':
with Manager() as manager:
d = manager.dict() l = manager.list(range(5))
p_list = []
for i in range(10):
p = Process(target=f, args=(d, l,i))
p.start()
p_list.append(p)
for res in p_list:
res.join() print(d)
print(l)

这里存在一个问题:数据共享 是不是要加锁

进程之间的数据同步LOCK:

用法与线程的一样:主要是为了防止进程抢占屏幕输出,避免输出错乱

from multiprocessing import Process, Lock

def f(l, i):
l.acquire()
try:
print('hello world', i)
finally:
l.release() if __name__ == '__main__':
lock = Lock() for num in range(10):
Process(target=f, args=(lock, num)).start()

进程池:

两种方法:
  • pool.apply
  • pool.apply_async
from multiprocessing import Pool
import os,time
def Foo(i):
time.sleep(2)
print("子进程",i,os.getpid())
def Bar(arg):
print("Exec done",arg,os.getpid())
if __name__=="__main__":
pool = Pool(3) #已经启动了10个进程,但是同一时刻只能有3个进程执行
for i in range(10):
#pool.apply(func=Foo,args=(i,)) #串行效果
#pool.apply_async(func=Foo,args=(i,))#异步方法,为了显示效果,必须加上,join。
pool.apply_async(func=Foo, args=(i,),callback=Bar) #异步使用回调函数,但是这个回调是在主进程中执行的,列如:在数据库连接的时候,如果在子进程连接,每个都要打开新的,不好
pool.close()
pool.join()#join之前,必须加上close,注意:close在前。

python 之进程篇的更多相关文章

  1. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  2. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  3. Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...

  4. Python【第一篇】基础介绍

    一.本节主要内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc文件 数据类型初识 数据运算 表达式if ...else语 ...

  5. Python3 与 C# 并发编程之~ 进程篇

      上次说了很多Linux下进程相关知识,这边不再复述,下面来说说Python的并发编程,如有错误欢迎提出- 如果遇到听不懂的可以看上一次的文章:https://www.cnblogs.com/dot ...

  6. 【Python】第一篇:python基础_1

    本篇内容 Python介绍 安装 第一个程序(hello,world) 变量 用户输入(input) 数据类型 数据运算 if判断 break和continue的区别 while 循环 一. Pyth ...

  7. Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型

    Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: ​ ​ ​ 每个对象都对应于一个可称为" 互斥锁&qu ...

  8. 《python开发技术详解》|百度网盘免费下载|Python开发入门篇

    <python开发技术详解>|百度网盘免费下载|Python开发入门篇 提取码:2sby  内容简介 Python是目前最流行的动态脚本语言之一.本书共27章,由浅入深.全面系统地介绍了利 ...

  9. 【Python】使用Supervisor来管理Python的进程

    来源 : http://blog.csdn.net/xiaoguaihai/article/details/44750073     1.问题描述 需要一个python的服务程序在后台一直运行,不能让 ...

随机推荐

  1. Vijos P1786 质因数分解【暴力】

    质因数分解 背景 NOIP2012普及组第一题 描述 已知正整数n是两个不同的质数的乘积试求出较大的那个质数. 格式 输入格式 输入只有一行包含一个正整数n. 输出格式 输出只有一行包含一个正整数p, ...

  2. HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)

    逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. hdu_1045Fire Net(二分图匹配)

    hdu_1045Fire Net(二分图匹配) 标签: 图论 二分图匹配 题目链接 Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Lim ...

  4. Kafka+Zookeeper集群搭建

    上次介绍了ES集群搭建的方法,希望能帮助大家,这儿我再接着介绍kafka集群,接着上次搭建的效果. 首先我们来简单了解下什么是kafka和zookeeper? Apache kafka 是一个分布式的 ...

  5. AspectCore动态代理中的拦截器详解(一)

    前言 在上一篇文章使用AspectCore动态代理中,简单说明了AspectCore.DynamicProxy的使用方式,由于介绍的比较浅显,也有不少同学留言询问拦截器的配置,那么在这篇文章中,我们来 ...

  6. 浅谈event.client、event.screen与event.offset

    每每看到event.client.event.screen与event.offset这几个,头都大了,今天又碰到了,特来总结下. 1.event.screenX与event.screenY. 首先,e ...

  7. Sqoop介绍

    Sqoop介绍 http://sqoop.apache.org http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html   1.什么是Sqoop? ...

  8. phpstudy中的mysql

    1.进入mysql命令台,执行 select version()即可 2status;

  9. dede从www跟目录迁移,网站空间

    图集缩略图表名dede_uploads                    字段url; 图集文章内部的图片表名dede_addonimages        字段imgurls 频道文章列表的图片 ...

  10. ProtoBuf 与 gRPC

    用 Protobuf 很久了,但是一直觉得很简单,所以就没有做一个总结,今天想尝试一下 gRPC,顺带就一起总结一下.ProtoBuf 是个老同志了,应该是 2010 的时候发布的,然后被广泛使用,目 ...