【问题标题】:TypeError: A Future or coroutine is requiredTypeError:需要 Future 或协程
【发布时间】:2015-05-28 20:08:17
【问题描述】:

我尝试在 asyncssh 上自动重新连接 ssh 客户端。 (SshConnectManager 必须留在后台并在需要时进行 ssh 会话)

class SshConnectManager(object):
def __init__(self, host, username, password, port=22):
    self._host = host
    self._username = username
    self._password = password
    self._port = port

    self.conn = None
    asyncio.async(self.start_connection)

@asyncio.coroutine
def start_connection(self):
    try:
        Client = self._create_ssh_client()
        self.conn, _ = yield from asyncssh.create_connection(Client,
                                                        self._host, port=self._port,
                                                        username=self._username,
                                                        password=self._password)
    except Exception as e:
        print("Connection error! {}".format(e))
        asyncio.async(self.start_connection())

def _create_ssh_client(self):
    class MySSHClient(asyncssh.SSHClient):
        parent = self
        def connection_lost(self, exc):
            self.parent._handle_connection_lost(exc)
    return MySSHClient

def _handle_connection_lost(self, exc):
    print('Connection lost on {}'.format(self.host))
    print(exc)
    asyncio.async(self.start_connection)


ssh1 = SshConnectManager(settings.host, settings.username, settings.password, settings.port)

asyncio.get_event_loop().run_until_complete(...)

请不要看 _create_ssh_client 或其他“haks”

问题是:

$ python3 main.py 
Traceback (most recent call last):
  File "main.py", line 75, in <module>
    ssh1 = SshConnectManager(settings.host, settings.username, settings.password, settings.port)
  File "main.py", line 22, in __init__
    asyncio.async(self.start_connection)
  File "/usr/lib/python3.4/asyncio/tasks.py", line 565, in async
    raise TypeError('A Future or coroutine is required')
TypeError: A Future or coroutine is required

但是 self.start_connection 是协程的!或不? 或者从同步代码启动异步任务的另一种方式是什么?

【问题讨论】:

  • 你看过/usr/lib/python3.4/asyncio/tasks.py第565行了吗?
  • 是的。但是为什么 start_connection 不是协程的呢?
  • 哦。需要调用它来获取 corutine...
  • @kolko 看起来你已经知道你需要做asyncio.async(self.start_connection())(缺少尾括号)。您在代码的其他地方也正确地做到了,所以我假设这只是一个错字?
  • 这不是错字:) 我错了。并且忘记在调试时尝试添加括号。

标签: python python-asyncio


【解决方案1】:

感谢@dano 和@boardrider 在 cmets 方面的帮助。 错误是 @asyncio.coroutine 返回函数需要调用以获取生成器对象。我忘了这样做。

固定版本:

class SshConnectManager(object):
def __init__(self, host, username, password, port=22):
    self._host = host
    self._username = username
    self._password = password
    self._port = port

    self.conn = None
    # FIX HERE
    asyncio.async(self.start_connection())

@asyncio.coroutine
def start_connection(self):
    try:
        Client = self._create_ssh_client()
        self.conn, _ = yield from asyncssh.create_connection(Client,
                                                        self._host, port=self._port,
                                                        username=self._username,
                                                        password=self._password)
    except Exception as e:
        print("Connection error! {}".format(e))
        asyncio.async(self.start_connection())

def _create_ssh_client(self):
    class MySSHClient(asyncssh.SSHClient):
        parent = self
        def connection_lost(self, exc):
            self.parent._handle_connection_lost(exc)
    return MySSHClient

def _handle_connection_lost(self, exc):
    print('Connection lost on {}'.format(self.host))
    print(exc)
    # AND HERE
    asyncio.async(self.start_connection())


ssh1 = SshConnectManager(settings.host, settings.username, settings.password, settings.port)

asyncio.get_event_loop().run_until_complete(...)

附:但我不明白为什么协程装饰器不能返回称为装饰器。 (这让我很困惑,我把它和扭曲的回调混淆了)。

我发现了如何记住这一点,有简单的情况,如果 start_connection 可以获取参数:

@asyncio.coroutine
def start_connection(self, some_arg):
    pass

所以,我可以简单地写:

asyncio.async(self.start_connection(some_val))

并且不需要在 asyncio.async 函数中添加额外的属性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 2014-03-10
    • 2021-11-23
    • 2015-03-16
    • 2018-09-29
    • 2014-06-15
    相关资源
    最近更新 更多