python 协程
2020-12-13 16:10
标签:目的 table string 服务端 enc tom top 客户 pip3 单线程实现并发,在应用程序里控制多个任务的切换+保存状态 greenlet只是提供了一种比generator更加便捷的切换方式,当切到一个任务执行时如果遇到io,那就原地阻塞,仍然是没有解决遇到IO自动切换来提升效率的问题。 遇到IO阻塞时会自动切换任务 from gevent import monkey;monkey.patch_all()一定要放到导入socket模块之前,否则gevent无法识别socket的阻塞 python 协程 标签:目的 table string 服务端 enc tom top 客户 pip3 原文地址:https://www.cnblogs.com/kingforn/p/11618298.html协程
一、协程的本质:
二、协程的目的:
三、补充:
四、优点
五、缺点
注意:单纯地切换反而会降低运行效率
#并发执行
import
time
def
producer():
g
=
consumer()
next
(g)
for
i
in
range
(
100
):
g.send(i)
def
consumer():
while
True
:
res
=
yield
start_time
=
time.time()
producer()
stop_time
=
time.time()
print
(stop_time
-
start_time)
#串行
import
time
def
producer():
res
=
[]
for
i
in
range
(
10000000
):
res.append(i)
return
res
def
consumer(res):
pass
start_time
=
time.time()
res
=
producer()
consumer(res)
stop_time
=
time.time()
print
(stop_time
-
start_time)
greenlet
注意:单纯的切换(在没有io的情况下或者没有重复开辟内存空间的操作),反而会降低程序的执行速度
#pip3 install greenlet
from
greenlet
import
greenlet
import
time
def
eat(name):
print
(
‘%s eat 1‘
%
name)
time.sleep(
2
)
g2.switch(
‘tom‘
)
print
(
‘%s eat 2‘
%
name)
g2.switch()
def
play(name):
print
(
‘%s play 1‘
%
name )
g1.switch()
print
(
‘%s play 2‘
%
name )
g1
=
greenlet(eat)
g2
=
greenlet(play)
g1.switch(
‘tom‘
)
"""
tom eat 1
tom play 1
tom eat 2
tom play 2
"""
gevent
一、用法:
二、补充:
#pip3 install gevent
from
gevent
import
monkey;monkey.patch_all()
import
gevent
import
time
def
eat(name):
print
(
‘%s eat 1‘
%
name)
time.sleep(
3
)
print
(
‘%s eat 2‘
%
name)
def
play(name):
print
(
‘%s play 1‘
%
name)
time.sleep(
2
)
print
(
‘%s play 2‘
%
name)
start_time
=
time.time()
g1
=
gevent.spawn(eat,
‘tom‘
)
g2
=
gevent.spawn(play,
‘rose‘
)
g1.join()
g2.join()
stop_time
=
time.time()
print
(stop_time
-
start_time)
"""
tom eat 1
rose play 1
rose play 2
tom eat 2
3.003171920776367
"""
from
gevent
import
monkey;monkey.patch_all()
import
gevent
import
time
def
eat(name):
print
(
‘%s eat 1‘
%
name)
time.sleep(
3
)
print
(
‘%s eat 2‘
%
name)
def
play(name):
print
(
‘%s play 1‘
%
name)
time.sleep(
2
)
print
(
‘%s play 2‘
%
name)
g1
=
gevent.spawn(eat,
‘tom‘
)
g2
=
gevent.spawn(play,
‘rose‘
)
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
三、通过gevent实现单线程下的socket并发
"""
服务端
#基于gevent实现
"""
from
gevent
import
monkey,spawn;monkey.patch_all()
from
socket
import
*
def
communicate(conn):
while
True
:
try
:
data
=
conn.recv(
1024
)
if
not
data:
break
conn.send(data.upper())
except
ConnectionResetError:
break
conn.close()
def
server(ip,port):
server
=
socket(AF_INET, SOCK_STREAM)
server.bind((ip,port))
server.listen(
5
)
while
True
:
conn, addr
=
server.accept()
spawn(communicate,conn)
server.close()
if
__name__
=
=
‘__main__‘
:
g
=
spawn(server,
‘127.0.0.1‘
,
8090
)
g.join()
"""
客户端
"""
from
socket
import
*
from
threading
import
Thread,currentThread
def
client():
client
=
socket(AF_INET,SOCK_STREAM)
client.connect((
‘127.0.0.1‘
,
8090
))
while
True
:
client.send((
‘%s hello‘
%
currentThread().getName()).encode(
‘utf-8‘
))
data
=
client.recv(
1024
)
print
(data.decode(
‘utf-8‘
))
client.close()
if
__name__
=
=
‘__main__‘
:
for
i
in
range
(
500
):
t
=
Thread(target
=
client)
t.start()