操作系统OS,Python

留坑

参考:

  1. https://en.wikipedia.org/wiki/Coroutine
  2. https://zh.wikipedia.org/wiki/协程
  3. http://www.cnblogs.com/xybaby/p/6323358.html

值得注意的点:

  1. Python对协程的支持是通过generator实现的。
  2. Python中,generator的send和throw方法使得generator很像一个协程(coroutine), 但是generator只是一个半协程(semicoroutines),python doc是这样描述的:“All of this makes generator functions quite similar to coroutines; they yield multiple times, they have more than one entry point and their execution can be suspended. The only difference is that a generator function cannot control where should the execution continue after it yields; the control is always transferred to the generator’s caller.
  3. 一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。(多进程+协程)
  4. greenlet是真正的协程
  5. Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。

例子1. 用协程实现生产者,消费者模型

  1. 参考:https://blog.csdn.net/pfm685757/article/details/49924099
  2. 参考:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432090171191d05dae6e129940518d1d6cf6eeaaa969000
"""
    1. 用协程实现消费者生产者模型
    2. Python对协程的支持是通过generator实现的
    3. 有yield的话,就是generator
    4. 整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
"""

def consumer():
    r = ''
    while True:
        # n为send过来的值
        # yield类似于断点,有两个作用。
        # 1. 生成值
        # 2. 在这里断点,交出控制权。切换到另外一个协程
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c): 
    #start generator with None
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        #启动生成器,并附带一个值,r接收yield生成的值
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()

produce(c)

例子2. 遇到IO阻塞时自动切换任务,based on gevent,greenlet,monkey

from gevent import monkey; monkey.patch_all()
import gevent
from  urllib.request import urlopen
 
def f(url):
    print('GET: %s' % url)
    resp = urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))
 
gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://www.baidu.com/'),
])

例子3. 单线程下实现多socket并发,based on gevent

server.py

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 + '  [server]'.encode('utf-8'))
            if not data:
                conn.shutdown(socket.SHUT_WR)
 
    except Exception as ex:
        print(ex)
    finally:
        conn.close()
if __name__ == '__main__':
    server(8006)

client.py

import socket
import threading

def sock_conn():

    client = socket.socket()

    client.connect(("localhost",8006))
    count = 0
    while True:
        #msg = input(">>:").strip()
        #if len(msg) == 0:continue
        #从客户端收到的数据
        client.send( ("hello %s" %count).encode("utf-8"))

        #从服务器端收到的数据
        data = client.recv(1024)

        print("[%s]recv from server:" % threading.get_ident(),data.decode()) #结果
        count +=1
    client.close()


for i in range(100):
    t = threading.Thread(target=sock_conn)
    t.start()
原文地址:https://www.cnblogs.com/allen2333/p/8940060.html