简体   繁体   English

异步-启动无限循环。create_connection()

[英]asyncio - launching infinite loop.create_connection()

I've been trying trying with no luck to create a endless chain of client instances. 我一直在尝试尝试创建无尽的客户端实例链。

I'm developing an asyncio app, this app among many others things, like running a server with loop.create_server(), needs every 10 seconds to connect to a list of servers, send some data and then disconnect. 我正在开发一个异步应用程序,该应用程序还有很多其他事情,例如使用loop.create_server()运行服务器,需要每10秒连接到服务器列表,发送一些数据然后断开连接。

I keep getting 2 errors: "runtimeError: Event loop is running." 我不断收到2个错误:“ runtimeError:事件循环正在运行。” or "asyncio > Task was destroyed but it is pending!" 或“异步>任务已销毁,但仍在等待中!”

The code down below works. 下面的代码有效。

import asyncio
from tcp.client import Client


def send_to_peers(data):
    for index in range(1, 3): #this for-loop just for simulating a list of peers
    try:
        loop = asyncio.get_event_loop()
        coro = loop.create_connection(lambda: Client(), '127.0.0.1', 10000 + index)
        _, proto = loop.run_until_complete(coro)
        msg = data + "-" + str(index) + "\n"
        proto.transport.write(str.encode(msg))
        proto.transport.close()
    except ConnectionRefusedError as exc:
        print(exc)

def infinite():
    for index in range(5): #again this should be a While True:
        #there should be here an asyncio.sleep(10)
        send_to_peers(str(index))

infinite()

But when I call it from the main_loop things start to break. 但是当我从main_loop调用它时,事情开始崩溃。

async def infinite_loop():
    for index in range(5):
        print("loop n " + str(index))
        task = asyncio.Task(send_to_peers(str(index)))
        await asyncio.sleep(10)
        task.cancel()
        with suppress(asyncio.CancelledError):
            await task

main_loop = asyncio.get_event_loop()
main_loop.run_until_complete(infinite_loop())
main_loop.run_forever()

I've tried to giving the main_loop to send_to_peers , giving it to the Client(loop) class,I tried to stoop & close the loop, delete the task, use weird combination of ensure_future but nothing works. 我试图将main_loop赋予send_to_peers,将其提供给Client(loop)类,我试图弯腰并关闭循环,删除任务,使用sure_future的怪异组合,但没有任何效果。

I googled as much as I could, I read it is not good to nest infinite loops but i didn't find any other way. 我尽可能地用Google搜索,我读到嵌套无限循环不好,但是我没有找到其他方法。

My last hope is to use threading but even if I think it will work, it won't be an elegant solution, nor the right one. 我最后的希望是使用线程,但是即使我认为它可以工作,也不会是一个优雅的解决方案,也不是一个正确的解决方案。

I'm used to work with Node so please excuse me if i made a silly mistake, I thought that after 2 weeks i could make it but here I am. 我曾经和Node一起工作过,所以如果我犯了一个愚蠢的错误,请原谅,我认为两周后我可以做到,但是我来了。

I would really appreciate any help. 我真的很感谢您的帮助。 I'm stuck. 我被卡住了。 Thanks! 谢谢!

PS: The Client() class is very basic: PS:Client()类非常基础:

import asyncio
import logging
import sys

logging.basicConfig(
    level=logging.DEBUG,
    format='%(name)s > %(message)s',
    stream=sys.stderr
)

class Client(asyncio.Protocol):

    def __init__(self):
        self.log = logging.getLogger('client')
        self.address = None
        self.transport = None

    def connection_made(self, transport):
        self.transport = transport
        self.address = transport.get_extra_info('peername')
        self.log.debug('{}:{} connected'.format(*self.address))

    def data_received(self, data):
            self.log.debug('{}:{} just sent {!r}'.format(*self.address, data))

    def eof_received(self):
        self.log.debug('{}:{} sent EOF'.format(*self.address))

    def connection_lost(self, error=""):
        self.log.debug('{}:{} disconnected'.format(*self.address))
        self.transport.close()

I keep getting 2 errors: "runtimeError: Event loop is running." 我不断收到2个错误:“ runtimeError:事件循环正在运行。” or "asyncio > Task was destroyed but it is pending!" 或“异步>任务已销毁,但仍在等待中!”

As you discovered, asyncio event loops do not nest . 如您所见,asyncio事件循环不嵌套

To remove the nesting, you should define send_to_peers as a coroutine using async def . 要删除嵌套,您应该使用async defsend_to_peers定义为协程。 Inside it loop.run_until_complete(coro) should be changed to await coro . 在它里面loop.run_until_complete(coro)应该更改为loop.run_until_complete(coro) await coro Once send_to_peers is a coroutine, you can call it: 一旦send_to_peers是一个协程,就可以调用它:

  • from blocking code such as infinite using loop.run_until_complete(send_to_peers(...)) 使用loop.run_until_complete(send_to_peers(...))阻止代码infinite

  • from async code such as infinite_loop using await send_to_peers(...) . 从异步代码(例如infinite_loop使用await send_to_peers(...)

In case of infinite_loop , you can implement the timeout using asyncio.wait_for : 如果是infinite_loop ,则可以使用asyncio.wait_for实现超时:

try:
    await asyncio.wait_for(send_to_peers(str(index)), 10)
except asyncio.TimeoutError:
    # ... timeout ...

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

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