Python 3.x 具有持久连接的asyncio

Python 3.x 具有持久连接的asyncio,python-3.x,python-asyncio,Python 3.x,Python Asyncio,免责声明:这可能是一个非常基本的问题,但我只是不理解这个概念,因此无法实现我想要的 我正在尝试使用asyncio实现基本的echo客户端服务器。我从文档中包含的示例开始 我想要实现的是一个持久连接,客户机可以在任何时间而不是立即连接向服务器发送一些数据,然后读取响应(如果有)。连接两端必须保持打开状态,直到显式关闭 我是用协议样本做的。在阅读其他问题/文档时,我似乎可以使用loop.call\u later()实现这一点,但这真的是一个好的解决方案吗?理想情况下,我希望使用队列,以便能够即时响应

免责声明:这可能是一个非常基本的问题,但我只是不理解这个概念,因此无法实现我想要的

我正在尝试使用asyncio实现基本的echo客户端服务器。我从文档中包含的示例开始

我想要实现的是一个持久连接,客户机可以在任何时间而不是立即连接向服务器发送一些数据,然后读取响应(如果有)。连接两端必须保持打开状态,直到显式关闭

我是用协议样本做的。在阅读其他问题/文档时,我似乎可以使用
loop.call\u later()
实现这一点,但这真的是一个好的解决方案吗?理想情况下,我希望使用
队列
,以便能够即时响应新数据包

我最终得到了这段代码,名为from'MyProtocol.init`:

    @asyncio.coroutine
    def writer():
        global out_queue
        while True:
            packt = yield from out_queue.get()
            print("yeahhh packet yummy")
            data = bytes(packt.to_json(), 'ascii')
            self.transport.write(data)

    asyncio.async(writer())
但这没有任何作用。我假设当从主客户机代码插入一个新项目时,它会立即打印出消息。什么都没发生

进一步的调试显示队列已满,但out_queue.get()协同路由永远不会返回。最初,out_queue.put甚至在最初的.get()调用中将项目直接放入服务生,但好像循环没有运行。它与用于整个客户端连接的循环相同(我创建了一个新的循环,因为我将所有内容都放在了一个线程中)。我已经检查过了,从.put()调用进行的相应调用都是针对这个循环的

哦,以防万一:我在Python3.3上运行它,由pip安装asyncio

更新:这是我尝试将项目插入队列的方式:

def send_packet(loop, queue, packet):
    # this runs in main thread, not the loop thread

    def f():
        print("putting packet into queue")
        queue.put_nowait(packet)  # MUST NOT use .put() as it's a coroutine

    loop.call_soon_threadsafe(f)
    # !!! next one doesn't work !!!
    # loop.call_soon_threadsafe(any_normal_function_with_coroutine_calls())

打印永远不会执行。

queue.get()在queue.put()之后永远不会唤醒的唯一原因是:您使用隐式循环创建队列(并且可能等待来自此循环的项目),但使用另一个循环实例推送数据。

实际上,我从另一个线程推送它们。但我也尝试从添加了“loop.call_soon_threadsafe()”的函数中推送它们,但该函数根本没有被调用。NVM,关于如何使用call_soon_threadsafe()的文档并不特别清楚。我假设任何旧函数都可以,但事实证明它不是。。。问题已用适当的解决方案更新call_soon、call_later和call_soon_threadsafe accept regular function,而不是Corroutine。Fresh asyncio对其进行了检查。不,它可以是任何函数。但如果您传递生成器函数(内部带有
yield
yield from
的函数),asyncio将不会释放(unyield),该生成器和代码将不会执行
asyncio.async
创建执行生成器展开的
asyncio.Task
。这就是任务展开的工作方式:它将下一个切片的执行从一个产量安排到下一个产量,再到
循环。很快调用\u
.call_soon
需要下一次循环迭代,并使用ask for socket轮询(可能是即时且非常快速的,但无论如何都是syscall)来执行。