【问题标题】:Python: Combination of cmd and asyncio (for WAMP / autobahn)Python:cmd 和 asyncio 的组合(用于 WAMP / 高速公路)
【发布时间】:2017-12-08 09:51:52
【问题描述】:

概述

我正在尝试为 WAMP 应用程序实现一个简单的命令行界面。

对于 WAMP 实现,使用了autobahn python 包。

我想要一个交互式外壳,所以我决定使用cmd 模块来解析输入。不幸的是,我无法将autobahnasyncio 性质与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 函数内部工作得非常好,所以我觉得我的问题也必须有一个简单而精简的解决方案。

任何建议将不胜感激!

【问题讨论】:

    标签: python python-asyncio autobahn wamp-protocol python-cmd


    【解决方案1】:

    事实证明,这个问题已经有了解决方案。

    autobahn 有两个版本,一个使用aysncio,一个使用来自twisted 的异步回调。

    crochet 包允许使用来自同步上下文的twisted-callbacks,因此提供了一个解决方案。

    简单的解决方案

    autobahn-sync 包是高速公路的 crochet 包装器,它使得从 cmd.Cmd(或其他任何地方)调用 RCP 变得很简单:

    import autobahn_sync
    
    autobahn_sync.run(url='example.com', realm='myrealm')
    autobahn_sync.call(u'com.example.add2', a, b)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      相关资源
      最近更新 更多