python异步和进程_12.python进程\协程\异步IO

进程

Python中的多线程无法利用多核优势 , 所以如果我们想要充分地使用多核CPU的资源 , 那么就只能靠多进程了

multiprocessing模块中提供了Process , Queue , Pipe , Lock , RLock , Event , Condition等组件 , 与threading模块有很多相似之处

1.创建进程

from multiprocessing importProcessimporttimedeffunc(name):

time.sleep(2)print('hello',name)if __name__ == '__main__':

p= Process(target=func,args=('derek',))

p.start()#p.join()

print('end...')

View Code

2.进程间通讯

(1)Queue

不同进程间内存是不共享的,要想实现两个进程间的数据交换。进程间通信有两种主要形式 , 队列和管道

from multiprocessing import Process, Queue #Queue是进程排列

deff(test):

test.put('22') #通过创建的子进程往队列添加数据,实线父子进程交互

if __name__ == '__main__':

q= Queue() #父进程

q.put("11")

p= Process(target=f, args=(q,)) #子进程

p.start()

p.join()print("取到:",q.get_nowait())print("取到:",q.get_nowait())#父进程在创建子进程的时候就把q克隆一份给子进程#通过pickle序列化、反序列化,来达到两个进程之间的交互

结果:

取到:11取到:22

Queue

(2)Pipe(管道)

The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way).

from multiprocessing importProcess, Pipedeff(conn):

conn.send('11')

conn.send('22')print("from parent:",conn.recv())print("from parent:", conn.recv())

conn.close()if __name__ == '__main__':

parent_conn, child_conn= Pipe() #生成管道实例,可以互相send()和recv()

p= Process(target=f, args=(child_conn,))

p.start()print(parent_conn.recv()) #prints "11"

print(parent_conn.recv()) #prints "22"

parent_conn.send("33") #parent 发消息给 child

parent_conn.send("44")

p.join()

Pipe

3.Manager

进程之间是相互独立的 ,Queue和pipe只是实现了数据交互,并没实现数据共享,Manager可以实现进程间数据共享 。

Manager还支持进程中的很多操作 , 比如Condition , Lock , Namespace , Queue , RLock , Semaphore等

from multiprocessing importProcess, Managerimportosdeff(d, l):

d[os.getpid()]=os.getpid()

l.append(os.getpid())print(l)if __name__ == '__main__':

with Manager() as manager:

d= manager.dict() #{} #生成一个字典,可在多个进程间共享和传递

l= manager.list(range(5)) #生成一个列表,可在多个进程间共享和传递

p_list =[]for i in range(2):

p= Process(target=f, args=(d, l))

p.start()

p_list.append(p)for res in p_list: #等待结果

res.join()print(d)print(l)

View Code

4.lock

from multiprocessing importProcess, Lockdeff(l, i):#l.acquire()

print('hello world', i)#l.release()

if __name__ == '__main__':

lock=Lock()for num in range(100):

Process(target=f, args=(lock, num)).start() #要把lock传到函数的参数l

#lock防止在屏幕上打印的时候会乱

lock

5.进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。

进程池中有以下几个主要方法:

apply:从进程池里取一个进程并执行

apply_async:apply的异步版本

terminate:立刻关闭线程池

join:主进程等待所有子进程执行完毕,必须在close或terminate之后

close:等待所有进程结束后,才关闭线程池

from multiprocessing importProcess, PoolimporttimeimportosdefFoo(i):

time.sleep(2)print("in process",os.getpid())return i + 100

defBar(arg):print('-->exec done:', arg,os.getpid())if __name__ == '__main__': #多进程,必须加这一句(windows系统)

pool = Pool(processes=3) #允许进程池同时放入3个进程

print("主进程",os.getpid())for i in range(10):

pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调,执行完Foo(),接着执行Bar()

#pool.apply(func=Foo, args=(i,)) #串行

print('end')

pool.close()

pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。必须先close(),再join()

Pool

协程

1.简介

协程(Coroutine) : 是单线程下的并发 , 又称微线程 , 纤程 . 协程是一种用户态的轻量级线程 , 即协程有用户自己控制调度

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。

协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态

使用协程的优缺点

优点 :

协程的切换开销更小 , 属于程序级别的切换 , 更加轻量级

单线程内就可以实现并发的效果 , 最大限度利用CPU

缺点 :

协程的本质是单线程下 , 无法利用多核 , 可以是一个程序开启多个进程 , 每个进程内开启多个线程 , 每个线程内开启协程

协程指的是单个线程 , 因而一旦协程出现阻塞 将会阻塞整个线程

2.Greenlet

greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator

手动切换

from greenlet importgreenletdeftest1():print(12)

gr2.switch()#到这里切换到gr2,执行test2()

print(34)

gr2.switch()#切换到上次gr2运行的位置

deftest2():print(56)

gr1.switch()#切换到上次gr1运行的位置

print(78)

gr1= greenlet(test1) #启动一个协程gr1

gr2 = greenlet(test2) #启动一个协程gr2

gr1.switch()#开始运行gr1

greenlet

3.Gevent

Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。

(1)IO阻塞自动切换

importgeventdeffoo():print('Running in foo')

gevent.sleep(2)print('阻塞时间最长,最后运行')defbar():print('running in bar')

gevent.sleep(1)print('foo()还在阻塞,这里第二个运行')deffunc3():print("running in func3")

gevent.sleep(0)print("其它两个还在IO阻塞先运行")#创建协程实例

gevent.joinall([

gevent.spawn(foo),#生成,

gevent.spawn(bar),

gevent.spawn(func3),

])#遇到IO自动切换

结果:

Runninginfoo

runninginbar

runninginfunc3

其它两个还在IO阻塞先运行

foo()还在阻塞,这里第二个运行

阻塞时间最长,最后运行

Process finished with exit code 0

View Code

由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:

(2)爬虫例子:

from urllib importrequestimportgevent,timefrom gevent importmonkey

monkey.patch_all()#作用:把当前程序的所有的io操作给我单独的做上标记

deff(url):print('GET: %s' %url)

resp=request.urlopen(url)

data=resp.read()print('%d bytes received from %s.' %(len(data), url))#同步需要的时间

urls = ['https://www.python.org/','https://www.yahoo.com/','https://github.com/']

time_start=time.time()for url inurls:

f(url)print("同步cost",time.time() -time_start)#下面是异步花费的时间

async_time_start =time.time()

gevent.joinall([

gevent.spawn(f,'https://www.python.org/'),

gevent.spawn(f,'https://www.yahoo.com/'),

gevent.spawn(f,'https://github.com/'),

])print("异步cost",time.time() -async_time_start)

结果:

GET: https://www.python.org/

48954 bytes received from https://www.python.org/.

GET: https://www.yahoo.com/

491871 bytes received from https://www.yahoo.com/.

GET: https://github.com/

51595 bytes received from https://github.com/.

同步cost4.928282260894775GET: https://www.python.org/GET: https://www.yahoo.com/GET: https://github.com/

48954 bytes received from https://www.python.org/.494958 bytes received from https://www.yahoo.com/.51599 bytes received from https://github.com/.

异步cost1.4920852184295654

IO多路复用

详解:http://www.cnblogs.com/alex3714/articles/5876749.html

selectors模块

selectors基于select模块实现IO多路复用,调用语句selectors.DefaultSelector(),特点是根据平台自动选择最佳IO多路复用机制,调用顺序:epoll > poll > select

做一个socket servers

importselectorsimportsocket

sel= selectors.DefaultSelector() #根据平台自动选择最佳IO多路复用机制

defaccept(sock, mask):

conn, addr= sock.accept() #Should be ready

#print('accepted', conn, 'from', addr,mask)

conn.setblocking(False) #设置为非阻塞IO

sel.register(conn, selectors.EVENT_READ, read)#新连接注册read回调函数

#将conn和read函数注册到一起,当conn有变化时执行read函数

defread(conn, mask):

data= conn.recv(1024) #Should be ready

ifdata:print('echoing', repr(data), 'to', conn)

conn.send(data)#Hope it won't block

else:print('closing', conn)

sel.unregister(conn)

conn.close()

sock=socket.socket()

sock.bind(('localhost', 9999))

sock.listen(100)

sock.setblocking(False)#设置为非阻塞IO

sel.register(sock, selectors.EVENT_READ, accept)#将sock和accept函数注册到一起,当sock有变化时执行accept函数

whileTrue:

events= sel.select() #默认阻塞,有活动连接就返回活动的连接列表,监听[(key1,mask1),(key2),(mask2)]

for key, mask inevents:

callback= key.data #accept #1 key.data就是accept # 2 key.data就是read

callback(key.fileobj, mask) #key.fileobj= 文件句柄

#1 key.fileobj就是sock # 2 key.fileobj就是conn

server

client

importsocketimportsys

messages= [ b'This is the message.',

b'It will be sent',

b'in parts.',

]

server_address= ('localhost', 9999)#Create a TCP/IP socket

socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM) for i in range(5)]print(socks)#Connect the socket to the port where the server is listening

print('connecting to %s port %s' %server_address)for s insocks:

s.connect(server_address)for message inmessages:#Send messages on both sockets

for s insocks:print('%s: sending "%s"' %(s.getsockname(), message) )

s.send(message)#Read responses on both sockets

for s insocks:

data= s.recv(1024)print( '%s: received "%s"' %(s.getsockname(), data) )if notdata:print( 'closing socket', s.getsockname() )

mutlti conn socket client

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swift date 计算差_[Swift 设计模式] 适配器

更多内容,欢迎关注公众号:Swift花园喜欢文章?不如来个 ➕三连?关注专栏,关注我 将一个不兼容的对象转换成目标接口或者类,这是适配器模式的作用。下面这件东西是适配器模式在现实世界中最贴切的表达。 USB-…

委外订单_听听晚报-英特尔扩大芯片委外订单、苹果秋季或举行两场发布会

英特尔扩大芯片委外订单据外媒报道称,美国半导体厂商英特尔已与中国台湾芯片制造厂商台积电达成协议,明年开始采用后者7nm的优化版本6nm制程量产处理器或显卡,预估投片量将达到18万片。该消息发出后,资本市场反应剧烈,…

ios系统可以使用python吗_4. 在苹果系统上使用 Python

4.1.获取和安装 MacPython Mac OS X 10.8 附带 Apple 预安装的 Python 2.7 。 如果你愿意,可以从 Python 网站( https://www.python.org )安装最新版本的 Python 3 。 Python 的当前“通用二进制”版本可以在 Mac 的新 Intel 和传统 PPC CPU …

打开另外一个页面_如何在PDF页面中插入图片?

如何给PDF添加图片?有些时候为了丰富PDF的文档内容,需要添加一些图片,相比Word或PPT文档可以直接插入图片,而PDF的操作很多人可能并不熟悉,下面一起来看看如何在PDF文档中插入图片。关于PDF文档插入图片分为两种情况&a…

spring boot mybatis 整合_MyBatis学习:MyBatis和Spring整合

1. 整合的工程结构首先我们来看下整合之后的工程结构是什么样的。2. 配置文件在于spring整合之前,mybatis都是自己管理数据源的,然后sqlSessionFactory是我们自己去注入的,现在整合了,这些都要交给spring来管理了,来看…

华三路由交换配置命令_华三路由器交换机配置命令

路由器:1、进入SETUP模式Router#setup2、时间设置router#clock set hh:mm:ss date moth year3、router>show historyRouter>terminal history size lines4、router#show version5、router#show running-config6、router#show starup-config7、router(config)#hostname na…

python中缩进_python编程中的缩进是什么意思

Python最具特色的是用缩进来标明成块的代码。我下面以if选择结构来举例。if后面跟随条件,如果条件成立,则执行归属于if的一个代码块。 下面对比C语言来看一下if ( i > 0 ) { x 1; y 2; } 如果i > 0的话,我们将进行括号中所包括的两个…

返回后的数据处理_【掘金使用技巧2】掘金返回数据中时间的处理方法

掘金输出的时间数据处理方法掘金在为使用者提供数据时,有一类数据处理起来有些麻烦,这类数据就是时间数据。它们长这样:或者这样:查看一下它们的类型,发现有datetime,datetime64,Timestamp等等。这么多各种各样的类型&…

springboot jwt token前后端分离_为什么要 前后端分离 ?

作 者:互扯程序来 源:互扯程序广而告之:由于此订阅号换了个皮肤,系统自动取消了读者的公众号置顶。导致用户接受文章不及时。您可以打开订阅号,选择置顶(星标)公众号,重磅干货,第一时间送达&…

mysql优化模糊查询_MySQL的LIKE模糊查询优化

%xxx%这种方式对于数据量少的时候,我们倒可以随意用,但是数据量大的时候,我们就体验到了查询性能的问题,像老化的车子艰难趴着坡一样,并且这种方式并未使用到索引,而是全表扫描mysql 高效模糊查询 代替like…

分计算iv值_一文读懂评分卡的IV、KS、AUC、GINI指标

前言:当一张评分卡构建完成时,筛选出一组特征生成了分数,我们会想要知道这个分数是否靠谱,即是否可以依赖这个分数将好坏客户区分开来,这个时候就需要评判评分卡有效性的指标。测量评分卡好坏区分能力的指标有许多&…

mysql 层_mysql三层体系

为什么有连接池和线程池?每创建一个新的会话(或链接),mysql内部创建一个新的用户线程来提供服务,当连接被销毁,线程也被销毁.即一个连接有一个线程.这种创建链接和销毁链接都会消耗cpu性能.为了降低这种消耗,有了连接池和线程池.连接池(connection pool)&#xff1a…

react登录页面_React 实现路由拦截

接到个新项目,使用的是React,由于React没有属于自己的路由拦截方法,只有自己封装Route成高阶组件来实现,现记录下实现的方式:首先创建一个router文件,引入项目需要展示的组件 。export const routes [{pat…

mysql 严格模式查看,如何查找和禁用MySQL严格模式?

Hello everybody I wanted to find this mysql strict mode for whmcs and disable it but i didnt had a progressIm a newbie so sry if I didnt mention other thingsCan anyone help me?Im working on WHM/Cpanel解决方案To turn off (or on) mysql strict access from cp…

linux 查找文件夹_用python打造一个基于socket的文件(夹)传输系统

这段时间在学习python,接触到了网络编程中的socket这块,加上自己在用的Linux服务器都是原生支持python的,于是乎有了个做文件传输功能程序的想法。毕竟python语言中,有下载功能的框架一抓一大把,但是主机与主机间快速搭…

mysql gtid 备份恢复_MySQL基于gtid特性与xtrabackup的数据恢复

一、gtid特性介绍:GTID(global transaction identifier)是MySQL 5.6的新特性,可以唯一的标识一个事务,由UUIDTID组成:UUID是MySQL实例的唯一标识TID是该实例上已提交的事务的数量在主从复制中,GTID代替了classic的复制…

编码gbk的不可映射字符_Python基础:编码表和字符的故事

在计算机内部,都是每8位组成的一个个字节,比如我们使用"abc".encode()把abc转化成二进制byte类型,注意byte是不可变类型: 编码过程>>> abc.encode() # 把str字符变为bytes字节类型;字符是一个个连接…

java mysql数据库编程_java JDBC数据库(mysql)编程

什么是JDBC• JDBC(Java Data Base Connectivity,Java数据库连接)• 是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问• 它由一组用Java语言编写的类和接口组成JDBC访问数据库步骤• 1:加载一个Driver驱动要通过JDBC与数据库连接&#xf…

python数据分析包pandas_Python 数据分析包:pandas 基础

pandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 类似于 Numpy 的核心是 ndarray,pandas 也是围绕着 Series 和 DataFrame 两个核心数据结构展开的 。Series 和 DataFrame 分别对应于一维的序列和二维的表结构。pandas 约定俗成的导入方法如下&…

mysql 查询分析器中使用if_查询分析器中开发代码测试检查_MySQL

如果您像我一样,则可能已经花费了很多时间在查询分析器中开发代码。在您对代码感到满意之后,可以立即对开发服务器上的测试数据库运行一个或两个专设 测试。如果看起来没有什么问题,您便可以将代码投入生产。如果这是一段关键代码&#xff0c…