协程与异步

----------------------------------------
遇到io操作就切换
手动switch
from greenlet import greenlet  #协成


def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()  #再切换2

def test2():
    print(56)
    gr1.switch()
    print(78)


gr1 = greenlet(test1)      #启动一个协程
gr2 = greenlet(test2)
gr1.switch()    #手动切换   gevent  自动档
--------------------------------gevent(自动)----
import gevent


def func1():
    print('\033[31;1m在跟搞...\033[0m')
    gevent.sleep(2)
    print('\033[31;1m又回去跟继续跟搞...\033[0m')


def func2():
    print('\033[32;1m切换到了跟搞...\033[0m')
    gevent.sleep(1)
    print('\033[32;1m搞完了,回来继续跟海龙搞...\033[0m')


gevent.joinall([
    gevent.spawn(func1),
    gevent.spawn(func2),
    # gevent.spawn(func3),
])
--------------------------爬虫网页-----------

import gevent,time
from  urllib.request import urlopen
from gevent import monkey
monkey.patch_all()     #当前程序的io操作做标记

def f(url):
    print('GET: %s' % url)
    resp = urlopen(url)
    data = resp.read()
    # f=open("url.html","wb")
    # f.write(data)
    # f.close()  存到本地
    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 in urls:
    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)
--------------------server  协成-------io自动驱动---------------------

import sys
import socket
import time
import gevent

from gevent import socket, monkey

monkey.patch_all()


def server(port):
    s = socket.socket()
    s.bind(('0.0.0.0', port))
    s.listen(500)
    while True:
        cli, addr = s.accept()  #将请求交给一实例  创建一个线程
        gevent.spawn(handle_request, cli)


def handle_request(conn):
    try:
        while True:
            data = conn.recv(1024)
            print("recv:", data)
            conn.send(data)
            if not data:
                conn.shutdown(socket.SHUT_WR)

    except Exception as  ex:
        print(ex)
    finally:
        conn.close()


if __name__ == '__main__':
    server(8001)
    -------client-----
    import socket

HOST = 'localhost'  # The remote host
PORT = 8001  # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)
    # print(data)

    print('Received', repr(data))  #  格式化输出

s.close()
-------------------事件驱动与异步io-----------
通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
--https://www.cnblogs.com/alex3714/articles/5876749.html----
-------
当一个read操作发生时,它会经历两个阶段:
1. 等待数据准备 (Waiting for the data to be ready)
2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
正式因为这两个阶段,linux系统产生了下面五种网络模式的方案。
- 阻塞 I/O(blocking IO)
- 非阻塞 I/O(nonblocking IO)
- I/O 多路复用( IO multiplexing)
- 信号驱动 I/O( signal driven IO)
- 异步 I/O(asynchronous IO)
注:由于signal driven IO在实际中并不常用,所以我这只提及剩下的四种IO Model。
----------------------------------------------------------
异步io   星级服务
多路复用 (同步io)  最后read需要 wait--
--------------------
BSD:unix的分支    多路复用(以下方式  数据在内核里  user recv or read )
select()  :监测socket链接   最多只能维护1024个socket
poll:  65535限制
epoll:not  support epoll (linux 2.6  core  )   返回数据时指定活跃的链接  没有最大端口数
一个1g内存数据 10万台服务器    一个链接4k
 aio  模块 支持异步io
 nginx:其实是io多路复用
 python3.0 后  asyncio 模块:支持异步io
http://www.cnblogs.com/alex3714/articles/4372426.html
-------------------------------多路复用实用socket_Serer----(非阻塞状态)---
import select
import socket
import  queue
server = socket.socket()
server.bind(('localhost',9000))
server.listen(100)
server.setblocking(False)  #设置为不阻塞   没有链接就报错

inputs=[server,]    #监听自己
outputs=[]
#输入 输出  报错

while True:
    readable,writeale,exceptional=select.select(inputs,outputs,inputs)
    print(readable,writeale,exceptional)
    for  r in   readable:
        if r is server:  #如果是server  就有新链接
            conn,addr=server.accept()
            print("来了个新链接",addr)
            inputs.append(conn)  #现在数据不存在 ,无法接收  需要监测 input
        else:
            data=r.recv(1024)
            print("收到数据",data)
            r.send(data)
            print("send down....")



server.accept()
server.close()
--------------
import socket
HOST = 'localhost'  # The remote host
PORT = 9000  # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    # data = s.recv(1024)  #不接受数据
    # # print(data)
    #
    # print('Received', repr(data))  #  格式化输出

s.close()

--------------------放 queue-下次再发----------------
import select
import socket
import  queue
server = socket.socket()
server.bind(('localhost',9000))
server.listen(100)
server.setblocking(False)  #设置为不阻塞   没有链接就报错
msg_dic={}

inputs=[server,]    #监听自己
outputs=[]
#输入 输出  报错

while True:#select  会返回三个值
    readable,writeable,exceptional=select.select(inputs,outputs,inputs)
    print(readable,writeable,exceptional)
    for  r in   readable:
        if r is server:  #如果是server  就有新链接
            conn,addr=server.accept()
            print("来了个新链接",addr)
            inputs.append(conn)  #现在数据不存在 ,无法接收  需要监测 input
            msg_dic[conn]=queue.Queue()#初始化一个队列  后面存要返回给客户端的数据
        else:
            data=r.recv(1024)
            print("收到数据",data)
            msg_dic[r].put(data)
            outputs.append(r)#放入返回的链接队列里
            # r.send(data)
            # print("send down....")

    for w in writeable: #返回的数据
        data_to_client = msg_dic[w].get()
        w.send(data_to_client)  #返回给客户端元数据
        outputs.remove(w)  #下次不返回 数据 了
    for e  in  exceptional:
        if e in outputs:
            outputs.remove(e)

        inputs.remove(e)

        del msg_dic[e]

server.close()
-----------------
import socket
HOST = 'localhost'  # The remote host
PORT = 9000  # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)
    print(data)
    #
    print('Received', repr(data))  #  格式化输出

s.close()
---------select模块 默认epoll-------
import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print('accepted', conn, 'from', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        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', 10000))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select() #默认是阻塞
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)  #没建立好的r
      $$$ulimit -n
       ulimit   -SHn    65535

10天17。。。





你可能感兴趣的:(协程与异步)