Python: сочетание cmd и asyncio (для WAMP / автобан)
обзор
Я пытаюсь реализовать простой интерфейс командной строки для приложения WAMP.
Для реализации WAMP, autobahn
пакет Python используется.
Я хотел бы иметь интерактивную оболочку, поэтому я решил использовать cmd
модуль для разбора ввода. К сожалению, я не смог объединить asyncio
природа autobahn
с cmd
петля.
Код
В общем, я хотел бы иметь что-то похожее на это:
import argparse
import autobahn.asyncio.wamp as wamp
import cmd
class Shell(cmd.Cmd):
intro = 'Interactive WAMP shell. Type help or ? to list commands.\n'
prompt = '>> '
def __init__(self, caller, *args):
super().__init__(*args)
self.caller = caller
def do_add(self, arg):
'Add two integers'
a, b = arg.split(' ')
res = self.caller(u'com.example.add2', int(a), int(b))
res = res.result() # this cannot work and yields an InvalidStateError
print('call result: {}'.format(res))
class Session(wamp.ApplicationSession):
async def onJoin(self, details):
Shell(self.call).cmdloop()
def main(args):
url = 'ws://{0}:{1}/ws'.format(args.host, args.port)
print('Attempting connection to "{0}"'.format(url))
try:
runner = wamp.ApplicationRunner(url=url, realm=args.realm)
runner.run(Session)
except OSError as err:
print("OS error: {0}".format(err))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('realm', type=str)
parser.add_argument('host', type=str)
parser.add_argument('port', type=int)
main(parser.parse_args())
Это, очевидно, не может работать, так как результат не готов, когда result()
называется на будущее, но я не могу использовать await, так как Shell не async
сам.
Попытки решения
я нашел asynccmd
но я не мог понять, как использовать его с autobahn
и я в целом все еще немного ошеломлен внутренними asyncio
,
Используя простой цикл
try:
while(True):
a = int(input('a:'))
b = int(input('b:'))
res = await self.call(u'com.example.add2', a, b)
print('call result: {}'.format(res))
except Exception as e:
print('call error: {0}'.format(e))
внутри onJoin
Функция прекрасно работает, поэтому я чувствую, что для моей проблемы должно быть простое и простое решение.
Любые предложения будут высоко ценится!
1 ответ
Оказывается, уже есть решение этой проблемы.
autobahn
имеет две версии, одна с использованием aysncio
и один, использующий асинхронные обратные вызовы из twisted
,
Посылка crochet
позволяет использовать twisted
-отзывы от синхронного контекста и, следовательно, предлагает решение.
Простое решение
Посылка autobahn-sync
это crochet
-раппер для автобана и делает вызов RCP изнутри cmd.Cmd
(или где-нибудь еще) тривиально:
import autobahn_sync
autobahn_sync.run(url='example.com', realm='myrealm')
autobahn_sync.call(u'com.example.add2', a, b)