Python的asyncio同步工作

时间:2015-04-05 12:42:12

标签: python python-3.x asynchronous python-asyncio

我试图利用Python的新asyncio库来发送异步HTTP请求。我想在发送每个请求之前等待几毫秒(timeout变量) - 但当然 - 异步发送它们,而不是在每个请求发送后等待响应。

我正在执行以下操作:

@asyncio.coroutine
def handle_line(self, line, destination):
    print("Inside! line {} destination {}".format(line, destination))
    response = yield from aiohttp.request('POST', destination, data=line,
                               headers=tester.headers)
    print(response.status)
    return (yield from response.read())

@asyncio.coroutine
def send_data(self, filename, timeout):
    destination='foo'
    logging.log(logging.DEBUG, 'sending_data')
    with open(filename) as log_file:
        for line in log_file:
            try:
                json_event = json.loads(line)
            except ValueError as e:
                print("Error parsing json event")
            time.sleep(timeout)
            yield from asyncio.async(self.handle_line(json.dumps(json_event), destination))


loop=asyncio.get_event_loop().run_until_complete(send_data('foo.txt', 1))

我得到的输出(通过打印200个响应)看起来这个代码是同步运行的。我做错了什么?

1 个答案:

答案 0 :(得分:6)

这里有几个问题:

  1. 您应该使用asyncio.sleep,而不是time.sleep,因为后者会阻止事件循环。

  2. yield from调用后你不应该使用asyncio.async(self.handle_line(...)),因为这会使脚本阻塞,直到self.handle_line协程完成,这意味着你不能#39; t最终同时做任何事情;你处理每一行,等待处理完成,然后转到下一行。相反,您应该在不等待的情况下运行所有​​asyncio.async个调用,保存返回到列表的Task个对象,然后使用asyncio.wait等待它们全部完成开始他们所有。

  3. 把所有这些放在一起:

    @asyncio.coroutine
    def handle_line(self, line, destination):
        print("Inside! line {} destination {}".format(line, destination))
        response = yield from aiohttp.request('POST', destination, data=line,
                                   headers=tester.headers)
        print(response.status)
        return (yield from response.read())
    
    @asyncio.coroutine
    def send_data(self, filename, timeout):
        destination='foo'
        logging.log(logging.DEBUG, 'sending_data')
        tasks = []
        with open(filename) as log_file:
            for line in log_file:
                try:
                    json_event = json.loads(line)
                except ValueError as e:
                    print("Error parsing json event")
                yield from asyncio.sleep(timeout)
                tasks.append(asyncio.async(
                     self.handle_line(json.dumps(json_event), destination))
        yield from asyncio.wait(tasks)
    
    
    asyncio.get_event_loop().run_until_complete(send_data('foo.txt', 1))