在龙卷风协程函数中变量会发生什么?
我刚接触非阻塞IO的概念,有些地方不太明白,特别是关于协程的部分。考虑这段代码:
class UserPostHandler(RequestHandler):
@gen.coroutine
def get(self):
var = 'some variable'
data = json.loads(self.request.body)
yield motor_db.users.insert({self.request.remote_ip: data})#asynch non blocking db insert call
#success
self.set_status(201)
print var
当调用get
函数时,它会创建一个字符串var
。那么,当这个函数在等待motor.insert
完成时,这个变量会发生什么呢?我理解的“非阻塞”是指没有线程在等待IO调用完成,也就是说在等待的时候没有占用内存。那么,var
的值存在哪里呢?当执行恢复时,它又是怎么被访问到的呢?
任何帮助都非常感谢!
1 个回答
6
在执行 insert
的时候,var
的内存仍然在使用中,但 get
函数本身是“冻结”的,这样其他函数就可以继续执行。Tornado 的协程是通过 Python 的生成器来实现的,这意味着当遇到 yield
时,函数的执行可以暂时中断,然后在 yield
之后的地方再继续执行,并且函数的状态会被保留。下面是关于这种行为的描述,来自于介绍生成器的 PEP:
当遇到
yield
语句时,函数的状态会被“冻结”,并且返回的值会传递给调用.next()
的地方。这里的“冻结”是指所有的局部状态都会被保留,包括当前的局部变量绑定、指令指针和内部评估栈:保存的信息足够多,以便下次调用.next()
时,函数可以像yield
语句只是另一个外部调用一样继续执行。
@gen.coroutine
生成器里面有一些神奇的东西,它和 Tornado 的事件循环连接在一起,这样 insert
调用返回的 Future
就会被注册到事件循环中,这样当 insert
调用完成时,get
生成器就可以重新启动。