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)
Другие вопросы по тегам