Python 使用autbahn.asyncio.wamp以非阻塞方式运行多个应用程序会话

Python 使用autbahn.asyncio.wamp以非阻塞方式运行多个应用程序会话,python,python-3.x,python-asyncio,autobahn,wamp-protocol,Python,Python 3.x,Python Asyncio,Autobahn,Wamp Protocol,我试图同时在python中运行两个autobahn.asyncio.wamp.ApplicationSessions。在此之前,我使用中建议的对高速公路库的修改来实现这一点。我现在 需要更专业的解决方案 在谷歌搜索一段时间后,使用twisted库,而不是asyncio。我无法为autobahn库的asyncio分支找到类似的解决方案,因为它似乎没有使用电抗器 我遇到的主要问题是,ApplicationRunner.run()正在阻塞(这就是我以前将其外包给线程的原因),因此我不能在它之后运行第二

我试图同时在python中运行两个
autobahn.asyncio.wamp.ApplicationSession
s。在此之前,我使用中建议的对高速公路库的修改来实现这一点。我现在 需要更专业的解决方案

在谷歌搜索一段时间后,使用
twisted
库,而不是
asyncio
。我无法为
autobahn
库的
asyncio
分支找到类似的解决方案,因为它似乎没有使用
电抗器

我遇到的主要问题是,
ApplicationRunner.run()
正在阻塞(这就是我以前将其外包给线程的原因),因此我不能在它之后运行第二个
ApplicationRunner

我确实需要同时访问两个websocket频道,这似乎无法通过单个
ApplicationSession
实现

到目前为止,我的代码是:

from autobahn.asyncio.wamp import ApplicationSession
from autobahn.asyncio.wamp import ApplicationRunner
from asyncio import coroutine
import time


channel1 = 'BTC_LTC'
channel2 = 'BTC_XMR'

class LTCComponent(ApplicationSession):

    def onConnect(self):
        self.join(self.config.realm)

    @coroutine
    def onJoin(self, details):
        def onTicker(*args, **kwargs):
            print('LTCComponent', args, kwargs)

        try:
            yield from self.subscribe(onTicker, channel1)
        except Exception as e:
            print("Could not subscribe to topic:", e)

class XMRComponent(ApplicationSession):

    def onConnect(self):
        self.join(self.config.realm)

    @coroutine
    def onJoin(self, details):
        def onTicker(*args, **kwargs):
            print('XMRComponent', args, kwargs)

        try:
            yield from self.subscribe(onTicker, channel2)
        except Exception as e:
            print("Could not subscribe to topic:", e)

def main():
    runner = ApplicationRunner("wss://api.poloniex.com:443", "realm1", extra={})
    runner.run(LTCComponent)
    runner.run(XMRComponent) # <- is not being called


if __name__ == "__main__":

    try:
        main()
    except KeyboardInterrupt:
        quit()

    except Exception as e:
        print(time.time(), e)

正如我从
回溯中看到的那样,我们只到达了第2步,共4步

异步IO文档:
该模块提供了使用协程编写单线程并发代码、通过套接字和其他资源复用I/O访问的基础设施

因此,我放弃了使用
多线程

我可以想象以下三种选择:

  • 使用
    多处理
    而不是
    多线程
  • 使用
    coroutine
    内部
    asyncio循环执行
  • def onJoin(self,details)

  • 第二个方案,第一个选项使用
    多处理

    我可以启动两个
    asyncio循环
    ,因此
    appRunner.run(…)
    应该可以工作

    如果
    频道
    是唯一不同的频道,则可以使用one
    类应用程序会话
    。 如果需要传递不同的
    类应用程序会话
    请将其添加到
    args=

    class __ApplicationSession(ApplicationSession):
            # ...
            try:
                yield from self.subscribe(onTicker, self.config.extra['channel'])
            except Exception as e:
                # ...
    
    import multiprocessing as mp
    import time
    
    def ApplicationRunner_process(realm, channel):
            appRunner = ApplicationRunner("wss://api.poloniex.com:443", realm, extra={'channel': channel})
            appRunner.run(__ApplicationSession)
    
    if __name__ == "__main__":
        AppRun = [{'process':None, 'channel':'BTC_LTC'},
                  {'process': None, 'channel': 'BTC_XMR'}]
    
        for app in AppRun:
            app['process'] =  mp.Process(target = ApplicationRunner_process, args = ('realm1', app['channel'] ))
            app['process'].start()
            time.sleep(0.1)
    
        AppRun[0]['process'].join()
        AppRun[1]['process'].join()
    
    按照这种方法,我成功地通过asyncio设置start\u loop=False获得了相同的行为


    嗯,你说得对——那句话没有多大意义。
    run()。我指的是覆盖信号调用并在线程中启动单独事件循环的黑客解决方案。可能在编辑时丢失了。不幸的是,由于线程中没有当前事件循环,这仍然会引发
    RuntimeError
    。我们非常接近-代码运行,但当我尝试挂接到第二个通道时,似乎出现了错误消息<代码>2017-03-16T08:07:33 wamp.error.not_authorized:内部错误:领域自动激活尚未实施
    是对此的响应。这是代码问题还是API问题?谷歌搜索没有产生任何有意义的结果。更新了我的答案以涵盖这一点。请说明您是否使用了一个
    类ApplicationSession
    或不同的类?对于
    类ApplicationSession
    ,只使用了一个类定义。使用
    extras
    属性效果很好。
    class __ApplicationSession(ApplicationSession):
            # ...
            try:
                yield from self.subscribe(onTicker, self.config.extra['channel'])
            except Exception as e:
                # ...
    
    import multiprocessing as mp
    import time
    
    def ApplicationRunner_process(realm, channel):
            appRunner = ApplicationRunner("wss://api.poloniex.com:443", realm, extra={'channel': channel})
            appRunner.run(__ApplicationSession)
    
    if __name__ == "__main__":
        AppRun = [{'process':None, 'channel':'BTC_LTC'},
                  {'process': None, 'channel': 'BTC_XMR'}]
    
        for app in AppRun:
            app['process'] =  mp.Process(target = ApplicationRunner_process, args = ('realm1', app['channel'] ))
            app['process'].start()
            time.sleep(0.1)
    
        AppRun[0]['process'].join()
        AppRun[1]['process'].join()
    
    import asyncio
    from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
    
    runner1 = ApplicationRunner(url, realm, extra={'cli_id': 1})
    coro1 = runner1.run(MyApplicationSession, start_loop=False)
    
    runner2 = ApplicationRunner(url, realm, extra={'cli_id': 2})
    coro2 = runner2.run(MyApplicationSession, start_loop=False)
    
    asyncio.get_event_loop().run_until_complete(coro1)
    asyncio.get_event_loop().run_until_complete(coro2)
    asyncio.get_event_loop().run_forever()
    
    class MyApplicationSession(ApplicationSession):
    
        def __init__(self, cfg):
            super().__init__(cfg)
            self.cli_id = cfg.extra['cli_id']
    
       def onJoin(self, details):
            print("session attached", self.cli_id)