Python9-IO模型-day41

# 进程:启动多个进程,进程之间是由操作系统负责调用
# 线程:启动多个线程,真正由被cpu执行的最小单位实际是线程
# 开启一个线程,创建一个线程,寄存器、堆栈
# 关闭一个线程
# 协程
# 本质上是一个线程
# 能够在多个任务之间来切换来节省一些IO时间
# 协程中任务之间的切换也消耗时间,但是开销要远远小于进程和线程之间的切换
# 实现并发的手段
def consumer():
   while True:
        x = yield
        print('处理了数据:',x)

def producer():
    c = consumer()
    next(c)
    for i in range(10):
        print('生成了数据:',i)
        c.send(i)
producer()
# 真正的协程模块就是使用greenlet完成的切换

from greenlet import greenlet

def eat():
    print('eating start')
    g2.switch()
    print('eating end')
    g2.switch()
def play():
    print('playing start')
    g1.switch()
    print('playing end')
g1 = greenlet(eat)
g2 = greenlet(play)
g1.switch()
from gevent import monkey;monkey.patch_all()
import time
import gevent
def eat():
    print('eating start')
    time.sleep(1)
    print('eating end')

def play():
    print('playing start')
    time.sleep(1)
    print('playing end')
g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join()
g2.join()
# 同步和异步的列子
from gevent import monkey;monkey.patch_all()
import time
import gevent
def task():
    time.sleep(1)
    print(12345)
def sync():
    for i in range(10):
        task()
def async():
    g_lst = []
    for i in range(10):
        g = gevent.spawn(task)
        g_lst.append(g)
    gevent.joinall(g_lst)
sync()
async()
# 协程:能够在一个线程中实现并发效果的概念
# 依赖于能够规避一些在任务中的IO操作
# 在任务的执行过程中检测到io就切换到其他任务
# 爬虫的例子
# 请求过程中的IO等待
from gevent import  monkey;monkey.patch_all()
import gevent
from  urllib.request import urlopen
def get_url(url):
    response = urlopen(url)
    content = response.read().decode('utf-8')
    return len(content)

g1 = gevent.spawn(get_url,'http://www.baidu.com')
g2 = gevent.spawn(get_url,'http://www.taobao.com')
g3 = gevent.spawn(get_url,'http://www.sougou.com')
g4 = gevent.spawn(get_url,'http://www.hao123.com')
g5 = gevent.spawn(get_url,'http://www.cisco.com')
g6 = gevent.spawn(get_url,'http://www.cnblogs.com')
gevent.joinall([g1,g2,g3,g4,g5,g6])
print(g1.value)
print(g2.value)
print(g3.value)
print(g4.value)
print(g5.value)
print(g6.value)

 socket-协程

#server
from
gevent import monkey;monkey.patch_all() import socket import gevent def talk(conn): conn.send(b'hello') print(conn.recv(1024).decode('utf-8')) conn.close() sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() gevent.spawn(talk,conn) sk.close()
#client
import
socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) print(sk.recv(1024)) msg = input('>>>>').encode('utf-8') sk.send(msg) sk.close()
协程 在一个线程上,提高cpu的利用率
# 协程相比多线程的优势。切换效率提高了
# 同步:提交一个任务之后要等待这个任务执行完毕;
# 异步:只管提交任务;不等待这个任务执行完毕就可以做其他事情
# 阻塞:recv recvfrom accept
# 非阻塞

# 阻塞 运行状态---阻塞状态---就绪状态

非阻塞IO方式实现socke#server

#server
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False)
sk.listen()
conn_l = []
del_conn = []
while True:
try:
conn,addr = sk.accept() #不阻塞,但是没有连我会报错
print('建立连接!',addr)
conn_l.append(conn)

except BlockingIOError:
for con in conn_l:
try:
msg = con.recv(1024) #非阻塞,如果没有数据就报错
if msg == b'':
del_conn.append(con)
continue
print(msg)
conn.send(b'byebye')
except BlockingIOError:pass
for con in del_conn:
conn.close()
conn_l.remove(con)
del_conn.clear()
 
#client
import time
import  socket
import threading
def func():
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    sk.send(b'hello')
    time.sleep(1)
    print(sk.recv(1024))
    sk.close()
for i in range(20):
    threading.Thread(target=func).start()

 

 

IO多路复用-socket
#server
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False)
sk.listen()
read_lst = [sk]
while True:
    r_lst,w_lst,x_lst = select.select(read_lst,[],[])
    for i in r_lst:
        if i is sk:
            conn,addr = i.accept()
            read_lst.append(conn)
        else:
            ret = i.recv(1024)
            if ret == b'':
                i.close()
                read_lst.remove(i)
                continue
            print(ret)
            i.send(b'bybybybyby')
#client
import time
import  socket
import threading
def func():
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    sk.send(b'gogogog')
    time.sleep(3)
    print(sk.recv(1024))
    sk.close()
for i in range(20):
    threading.Thread(target=func).start()
原文地址:https://www.cnblogs.com/zhangtengccie/p/10423525.html