python协程基础知识可以先了解下之前的文章:
一篇文章了解Python中的协程、例子、协程的发展_巴山夜雨-CSDN博客_python 协程o
python3用asyncio很容易实现这种写法
python2的协程更加简单,要实现同步方式写异步代码,只要做些封装也可以实现
协程1Python 2 的yeild和send
生成器yeild和send,实现协程的老方法,只能实现协程基本功能,保存状态、实现函数的能暂停、恢复等。
# coding: utf-8
def coroutine_work():
print '->start work'
while True:
rc = (yield)
print '->work', rc
def coroutine_eat():
print '->start eat'
while True:
rc = (yield)
print '->eat', rc
cw = coroutine_work()
ce = coroutine_eat()
next(cw) # next启动work协程
next(ce) # next启动eat协程
cw.send('1')
ce.send('1')
cw.send('2')
ce.send('2')
ce.close()
cw.close()
即带yield关键字的函数被调用时候,返回的是一个生成器对象(generator object),函数的状态帧都保存了下来,执行send方法时在继续执行
跟据这个特性,即可以以同步的方式,些异步的代码
比如一个登录方法,验证密码需要异步去请去查询密码是否正确(如http)
可以这样这样些,
# 同步方式写异步代码,类似asyncio
def user_login(user, pw):
if user.is_valid():
# 角色能登录
http.request(url, user_id, pw, yid):
result = yield
if result is True:
print("登录成功")
else:
print("秘密错误,登录失败")
else:
print("登录失败")
yield_call(user_login)
主要做法就是,等http返回时候,通过yid去肇东对应的生成器对象,再去调用
参考封装代码:
g_yid2obj = {}
g_cur_add_yid = 0
class YieldObjectWarp(object):
def __init__(self, parent_id, func, *args, **kwargs):
global g_cur_add_yid
g_cur_add_yid += 1
self.m_yield_obj = func(g_cur_add_yid, *args, **kwargs)
g_yid2obj[g_cur_add_yid] = self
self.m_ParentID = parent_id
self.send(None)
def send(self, value):
try:
ret = self.m_yield_obj.send(value)
state, result = ret if ret else (False, None)
if state and self.m_ParentID:
g_yid2obj[self.m_ParentID].send((state, result))
except:
state, result = False, None
g_yid2obj.pop(id(self), None)
if self.m_ParentID:
g_yid2obj[self.m_ParentID].send((state, result))
return state, result
def close(self):
return self.m_yield_obj.close()
def yield_call(func, *args, **kwargs):
yobj = YieldObjectWarp(None, func, *args, **kwargs)
return yobj