在asycnio中使用threading.Timer [英] Using threading.Timer with asycnio

查看:96
本文介绍了在asycnio中使用threading.Timer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是python的ascynio功能的新手,我有一台服务器来处理来自浏览器的websocket请求.这是其工作方式的简化版本:

I'm new to python's ascynio feature and I have a server that processes websocket requests from a browser. Here's a simplified version of how it works:

@asyncio.coroutine
def web_client_connected(self, websocket):
    self.web_client_socket = websocket

    while True:
        request = yield from self.web_client_socket.recv()
        json_val = process_request(request)
        yield from self.socket_queue.put(json_val)

@asyncio.coroutine
def push_from_web_client_json_queue(self):
    while True:
        json_val = yield from self.socket_queue.get()
        yield from self.web_client_socket.send(json_val)

您有一个循环来查找来自客户端的Web套接字请求.当它得到一个值时,它将对其进行处理并将其值放入一个队列中.另一个循环正在该队列中寻找值,当发现一个队列时,它将处理后的值发送回Web套接字.相当简单,而且有效.

You have one loop looking for web socket requests coming in from the client. When it gets one, it processes it and puts the value onto a queue. Another loop is looking for values on that queue and when it finds one it sends processed value back out on the web socket. Pretty straight forward and it works.

我现在想做的是引入一个计时器.当请求到来并已完成处理时,我希望将计时器启动1分钟,而不是立即将响应放回队列.计时器结束后,我想将响应放入队列中.

What I want to do now it introduce a timer. When requests comes and and is done processing, instead of putting a response back on the queue immediately, I want to start a timer for 1 minute. When the timer is finished, then I want to put the response on the queue.

我尝试过类似的事情:

@asyncio.coroutine
def web_client_connected(self, websocket):
    self.web_client_socket = websocket

    while True:
        request = yield from self.web_client_socket.recv()
        json_val = process_request(request)
        t = threading.Timer(60, self.timer_done, json_val)
        t.start()

@asyncio.coroutine
def timer_done(self, args):
    yield from self.socket_queue.put(args)

虽然不起作用.永远不会调用timer_done方法.如果我删除了@asyncio.coroutine装饰器和yield from,则会调用timer_done,但随后无法调用self.socket_queue.put(args).

It doesn't work though. The timer_done method is never called. If I removed the @asyncio.coroutine decorator and yield from, then timer_done does get called but then call to self.socket_queue.put(args) doesn't work.

我认为我对这里的一些基本知识误解了.你如何做到的?

I think I'm misunderstanding something fundamental here. How do you do this?

推荐答案

装有计时器,请使用asyncio.ensure_future()

Insted of a timer, use asyncio.ensure_future() and asyncio.sleep():

@asyncio.coroutine
def web_client_connected(self, websocket):
    self.web_client_socket = websocket

    while True:
        request = yield from self.web_client_socket.recv()
        json_val = process_request(request)
        asyncio.ensure_future(web_client_timer(json_val))
        yield

@asyncio.coroutine
def web_client_timer(self, json_val):
    yield from asyncio.sleep(60)
    yield from self.socket_queue.put(json_val)

工作示例:

import asyncio


@asyncio.coroutine
def foo():
    print("enter foo")
    timers = []
    for i in range(10):
        print("Start foo", i)
        yield from asyncio.sleep(0.5)
        print("Got foo", i)
        timers.append(asyncio.ensure_future(timer(i)))
        yield
    print("foo waiting")
    # wait for all timers to finish
    yield from asyncio.wait(timers)
    print("exit foo")


@asyncio.coroutine
def timer(i):
    print("Setting timer", i)
    yield from asyncio.sleep(2)
    print("**** Timer", i)


loop = asyncio.get_event_loop()
resp = loop.run_until_complete(foo())
loop.close()

这篇关于在asycnio中使用threading.Timer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆