在龙卷风协程函数中变量会发生什么?

3 投票
1 回答
554 浏览
提问于 2025-04-18 16:56

我刚接触非阻塞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 生成器就可以重新启动。

撰写回答