AsyncSSH 创建 SFTP 客户端错误 - 太多值无法解压
AsyncSSH Create SFTP Client Error- too many values to unpack
我在 Sanic 应用程序(运行Asyncio 事件循环)中使用 asyncssh 库来创建 SFTP 客户端连接。在我的代码中我这样做:
class MyClass:
async def connect(self, host, username, password, port):
return await asyncssh.connect(host=host, port=port, username=username, password=password, known_hosts=None)
async def establish_sftp_client(self, conn):
return await conn.start_sftp_client()
# This is my invoker:
async def create_connection(self, <some args>):
conn = await self.connect()
sftp_client = await self.establish_sftp_client(conn)
...
return conn, sftp_client
当我尝试执行此操作时出现此错误:
Traceback (most recent call last):
File "/tmp/pycharm_projects/<MY SANIC APP>/requests/helpers.py", line 378, in establish_sftp_client
return await conn.start_sftp_client()
File "<MY SANIC APP>/venv/lib/python3.6/site-packages/asyncssh/misc.py", line 182, in __await__
return (yield from self._coro)
File "<MY SANIC APP>/venv/lib/python3.6/site-packages/asyncssh/connection.py", line 3503, in start_sftp_client
encoding=None)
ValueError: too many values to unpack (expected 3)
当我调试它并注销 start_sftp_client()
实际返回的内容时,我得到了这个:
(asyncssh.stream.SSHWriter object at 0x7f51bbb29dd8, asyncssh.stream.SSHReader object at 0x7f51bbb29da0, asyncssh.stream.SSHReader object at 0x7f51b99b7978, asyncssh.stream.SSHClientStreamSession object at 0x7f51bbb29f98)
所以它实际上返回了 4 个值...当我查看 asyncSSH 的源代码时,start_sftp_client() 实际上做了什么,它只寻找三个值:
writer, reader, _ = yield from self.open_session(subsystem='sftp', encoding=None)
所以抛出这个错误是有道理的...但是为什么呢?
当我从 python 控制台 运行 这个方法时——它工作得很好。从此脚本正确创建 SFTP 客户端:
import asyncssh, asyncio
async def x():
conn = await asyncssh.connect(host='<host'>, username='some name', password='some pass', port=22, known_hosts=None)
sftp = await conn.start_sftp_client()
print("sftp {}".format(sftp)) # This works!
asyncio.get_event_loop().run_until_complete(x())
在代码库中到处放置日志语句后,终于找到了这个问题的根本原因。这些行隐藏在一些晦涩的文件中:
@asyncio.coroutine
def open_session(self, *args, **kwargs):
chan, session = yield from self.create_session(CoreSSHClientStreamSession,
*args, **kwargs)
return (asyncssh.stream.SSHWriter(session, chan), asyncssh.stream.SSHReader(session, chan),
asyncssh.stream.SSHReader(session, chan, asyncssh.constants.EXTENDED_DATA_STDERR))
asyncssh.SSHClientConnection.open_session = open_session
最后一行覆盖了 asyncssh 中的 open_session 方法!
我在 Sanic 应用程序(运行Asyncio 事件循环)中使用 asyncssh 库来创建 SFTP 客户端连接。在我的代码中我这样做:
class MyClass:
async def connect(self, host, username, password, port):
return await asyncssh.connect(host=host, port=port, username=username, password=password, known_hosts=None)
async def establish_sftp_client(self, conn):
return await conn.start_sftp_client()
# This is my invoker:
async def create_connection(self, <some args>):
conn = await self.connect()
sftp_client = await self.establish_sftp_client(conn)
...
return conn, sftp_client
当我尝试执行此操作时出现此错误:
Traceback (most recent call last):
File "/tmp/pycharm_projects/<MY SANIC APP>/requests/helpers.py", line 378, in establish_sftp_client
return await conn.start_sftp_client()
File "<MY SANIC APP>/venv/lib/python3.6/site-packages/asyncssh/misc.py", line 182, in __await__
return (yield from self._coro)
File "<MY SANIC APP>/venv/lib/python3.6/site-packages/asyncssh/connection.py", line 3503, in start_sftp_client
encoding=None)
ValueError: too many values to unpack (expected 3)
当我调试它并注销 start_sftp_client()
实际返回的内容时,我得到了这个:
(asyncssh.stream.SSHWriter object at 0x7f51bbb29dd8, asyncssh.stream.SSHReader object at 0x7f51bbb29da0, asyncssh.stream.SSHReader object at 0x7f51b99b7978, asyncssh.stream.SSHClientStreamSession object at 0x7f51bbb29f98)
所以它实际上返回了 4 个值...当我查看 asyncSSH 的源代码时,start_sftp_client() 实际上做了什么,它只寻找三个值:
writer, reader, _ = yield from self.open_session(subsystem='sftp', encoding=None)
所以抛出这个错误是有道理的...但是为什么呢?
当我从 python 控制台 运行 这个方法时——它工作得很好。从此脚本正确创建 SFTP 客户端:
import asyncssh, asyncio
async def x():
conn = await asyncssh.connect(host='<host'>, username='some name', password='some pass', port=22, known_hosts=None)
sftp = await conn.start_sftp_client()
print("sftp {}".format(sftp)) # This works!
asyncio.get_event_loop().run_until_complete(x())
在代码库中到处放置日志语句后,终于找到了这个问题的根本原因。这些行隐藏在一些晦涩的文件中:
@asyncio.coroutine
def open_session(self, *args, **kwargs):
chan, session = yield from self.create_session(CoreSSHClientStreamSession,
*args, **kwargs)
return (asyncssh.stream.SSHWriter(session, chan), asyncssh.stream.SSHReader(session, chan),
asyncssh.stream.SSHReader(session, chan, asyncssh.constants.EXTENDED_DATA_STDERR))
asyncssh.SSHClientConnection.open_session = open_session
最后一行覆盖了 asyncssh 中的 open_session 方法!