简体   繁体   English

使用threading.Timer与asycnio

[英]Using threading.Timer with asycnio

I'm new to python's ascynio feature and I have a server that processes websocket requests from a browser. 我是python的ascynio功能的新手,我有一个服务器来处理来自浏览器的websocket请求。 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)

You have one loop looking for web socket requests coming in from the client. 您有一个循环正在查找来自客户端的Web套接字请求。 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. 另一个循环是在该队列上查找值,当它找到一个时,它会在Web套接字上发回处理后的值。 Pretty straight forward and it works. 相当直接,它的工作原理。

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. 当请求到来并且处理完毕,而不是立即将响应放回队列时,我想启动计时器1分钟。 When the timer is finished, then I want to put the response on the queue. 当计时器完成时,我想将响应放在队列上。

I've tried something like: 我尝试过类似的东西:

@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)

It doesn't work though. 它不起作用。 The timer_done method is never called. 永远不会调用timer_done方法。 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. 如果我删除了@asyncio.coroutine装饰和yield from ,然后timer_done不会被调用但随后打电话self.socket_queue.put(args)不起作用。

I think I'm misunderstanding something fundamental here. 我想我在这里误解了一些基本的东西。 How do you do this? 你怎么做到这一点?

Insted of a timer, use asyncio.ensure_future() and asyncio.sleep() : 使用asyncio.ensure_future()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)

Working example: 工作范例:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM