python之路——42

學習內容

協程
1.本質是一個線程
2.可以在多個任務之間切換節省io時間
3.協程中任務之間的切換也要消耗時間,可是開銷遠遠小於進程線程之間的切換
4.在任務的執行過程當中,檢測到IO就切換至他任務
5.爬蟲和socket相關的操做,可以使用協程
IO模型
1.阻塞IO
2.非阻塞IO
3.多路複用IO
1.select 機制 (window,linux) 操做系統循環列表中每個被監聽的項,看是否有讀操做
2.poll 機制 (linux) 能夠監聽對象比select多
select 和 poll 機制 都會隨着監聽項的增多,效率下降
3.epoll 機制 linux 更高級的算法,不是循環監聽

代碼區

1.消費者模型 函數間切換linux

def consumer():
    while True:
        x = yield
        print('消費了%s數據'%x)

def producer():
    c = consumer()
    next(c)
    for i in range(10):
        print('製造了%s數據'%i)
        c.send(i)
producer()

2.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()

3.gevent 異步app

from gevent import monkey;monkey.patch_all()
import time
import gevent

def task():
    print('******')
    time.sleep(1)


def sync():
    for i in range(5):
        print('sync:')
        task()

def async():
    c_list = []
    for i in range(5):
        print('async:')
        c = gevent.spawn(task)
        c_list.append(c)
    gevent.joinall(c_list)

sync()
async()

4.gevent 爬蟲異步

from gevent import monkey; monkey.patch_all()
from urllib.request import urlopen
import gevent
def func(url):
    ret = urlopen(url)
    ret = ret.read().decode('utf-8')
    return ret

url = 'http://www.baidu.com'
url1 = 'http://www.taobao.com'
url2 = 'http://www.qq.com'
url3 = 'http://www.hao123.com'

g = gevent.spawn(func,url)
g1 = gevent.spawn(func,url1)
g2 = gevent.spawn(func,url2)
g3 = gevent.spawn(func,url3)
gevent.joinall([g,g1,g2,g3])
print(g.value,g1.value,g2.value,g3.value)

5.gevent 實現socketserver socket

# server
import socket
from gevent import monkey;monkey.patch_all()
import gevent
def func(conn):
    conn.send(b'hello')
    ret = conn.recv(1024).decode('utf-8')
    print(ret)
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()

while 1 :
    conn, addr = sk.accept()
    gevent.spawn(func,conn)
conn.close()
sk.close()
#client
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))

ret = sk.recv(1024).decode('utf-8')
print(ret)
info = input('>>> ')
sk.send(info.encode('utf-8'))
sk.close()

6.阻塞IO實現socketserver async

#server
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False)
sk.listen()
conn_list = []
del_conn = []
while True:
    try:
        conn, addr = sk.accept()
        print('一個鏈接被創建')
        conn_list.append(conn)
    except BlockingIOError:
        for conn in conn_list:
            try:
                msg = conn.recv(1024)
                if msg == b'':
                    del_conn.append(conn)
                    continue
                print(msg)
                conn.send(b'bye bye')
            except BlockingIOError:
                pass
        for conn in del_conn:
            conn.close()
            conn_list.remove(conn)
        del_conn.clear()
#client
import socket,time
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(2):
    threading.Thread(target=func).start()

7. 多路複用 IO實現socketserver 函數

#server
import select
import socket

sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False)
sk.listen()

read_list = [sk]
while 1:
    r_list, w_list, x_list = select.select(read_list,[],[])
    for i in r_list:
        if i is sk:
            conn, addr = i.accept()
            read_list.append(conn)
        else:
            ret = i.recv(1024)
            if ret == b'':
                i.close()
                read_list.remove(i)
                continue
            print(ret)
            i.send(b'go')
#client
import socket,time
import threading
def func():
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    sk.send(b'hello')
    time.sleep(4)
    print(sk.recv(1024))
    sk.close()
for i in range(20):
    threading.Thread(target=func).start()
相關文章
相關標籤/搜索