我面临的问题是:
await
调用异步代码我在Python's Cmd class之上构建了一个自定义命令解释器。我为它提供了自定义的stdin和stdout。出于这个问题的目的,它看起来像这样:
import cmd
import sys
class CustomStream(object):
def readline(self):
return sys.stdin.readline()
def write(self, msg):
sys.stdout.write(msg)
def flush(self):
pass
class MyShell(cmd.Cmd):
def do_stuff(self, args):
print("Getting things done...")
def do_exit(self, args):
return True
stream = CustomStream()
shell = MyShell(stdin=stream, stdout=stream)
shell.use_rawinput = False
shell.cmdloop()
当Cmd
需要向用户阅读时,它将执行以下操作:
line = self.stdin.readline()
我想使用基于asyncio
的AsyncSSH库为自定义互操作器提供SSH接口。我的SSH代码很像Simple Server sample,它像这样读取标准输入接口(注意await
关键字):
line_from_client = (await self._process.stdin.readline()).rstrip('\n')
我尝试了很多事情,但是我无法根据Cmd对stdin的期望来键入SSH代码。在为CustomStream
提供老式的单线程接口时,我该如何使MyShell
对象在内部使用asyncio /协程?
答案 0 :(得分:0)
解决方案是修补cmdloop
方法以使其具有异步意识。
此代码是您设置后获得的Python 3.7.2 Cmd类cmdloop函数的副本
raw_input
设置为True
await
放在阅读行的前面此代码(aoicmd.py available as a gist)的结果:
async def adapter_cmdloop(self, intro=None):
"""Repeatedly issue a prompt, accept input, parse an initial prefix
off the received input, and dispatch to action methods, passing them
the remainder of the line as argument.
"""
self.preloop()
#This is the same code as the Python 3.7.2 Cmd class, with the
#following changes
# - Remove dead code caused by forcing use_rawinput=False.
# - Added a readline in front of readline()
if intro is not None:
self.intro = intro
if self.intro:
self.stdout.write(str(self.intro)+"\n")
stop = None
while not stop:
if self.cmdqueue:
line = self.cmdqueue.pop(0)
else:
self.stdout.write(self.prompt)
self.stdout.flush()
line = await self.stdin.readline()
if not len(line):
line = 'EOF'
else:
line = line.rstrip('\r\n')
line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
self.postloop()
在需要使用Cmd派生类的地方,例如MyShell
,请在运行时创建一个名为MyAsyncShell
的新类:
#Patch the shell with async aware cmdloop
MyAsyncShell = type('MyAsyncSHell', (MyShell,), {
'cmdloop' :aiocmd.adapter_cmdloop,
'use_rawinput':False,
})
按照您认为合适的方式实施write
和flush
,但您的阅读内容应如下所示:
async def readline(self):
return await my_implementation_of_readline()