扭曲 - 如何使许多Python代码无阻塞

时间:2018-01-12 01:08:47

标签: wamp twisted autobahn twisted.internet crossbar

我一直在努力让这个脚本按照书面顺序执行hub()中的代码。

hub()包含标准Python代码和使用Twisted和Crossbar执行I / O的请求。

但是,由于Python代码阻塞,因此reactor没有机会执行这些“发布”任务。 我的前端收到所有已发布的消息。

  1. 此代码是我实际处理的大量简化版本。真实的脚本(hub()和它调用的其他方法)超过1500行。修改所有这些功能以使其无阻塞并不理想。如果可以解决这个问题,我宁愿能够将更改隔离到像publish()这样的一些方法。
  2. 我玩过asyncawaitdeferLaterloopingCall等词语。我还没有找到一个在我的情况下帮助的例子。
  3. 有没有办法修改publish()(或hub()),以便他们按顺序发送消息?

    from autobahn.twisted.component import Component, run
    from twisted.internet.defer import inlineCallbacks, returnValue
    from twisted.internet import reactor, defer
    
    component = Component(
        transports=[
            {
                u"type": u"websocket",
                u"url": u"ws://127.0.0.1:8080/ws",
                u"endpoint": {
                    u"type": u"tcp",
                    u"host": u"localhost",
                    u"port": 8080,
                },
                u"options": {
                    u"open_handshake_timeout": 100,
                }
            },
        ],
        realm=u"realm1",
    )
    
    @component.on_join
    @inlineCallbacks
    def join(session, details):
        print("joined {}: {}".format(session, details))
    
        def publish(context='output', value='default'):
            """ Publish a message. """
            print('publish', value)
            session.publish(u'com.myapp.universal_feedback', {"id": context, "value": value})
    
        def hub(thing):
            """ Main script. """
            do_things
            publish('output', 'some data for you')
            do_more_things
            publish('status', 'a progress message')
            do_even_more_things
            publish('status', 'some more data')
            do_all_the_things
            publish('other', 'something else')
    
        try:
            yield session.register(hub, u'com.myapp.hello')
            print("procedure registered")
        except Exception as e:
            print("could not register procedure: {0}".format(e))
    
    
    if __name__ == "__main__":
        run([component])
        reactor.run()
    

2 个答案:

答案 0 :(得分:0)

您的join()函数是异步的(用@inlineCallbacks修饰,并且在正文中至少包含一个yield

在内部,它将函数hub()注册为WAMP RPC;然而,hub()并非异步。

同样,对session.publish()的调用也不会产生,因为异步调用应该是。

结果:您向eventloop添加了一堆事件,但是等到它们等待它们才会在应用程序关闭时刷新eventloop。

答案 1 :(得分:0)

您需要使您的功能中心和发布异步。

@inlineCallbacks
def publish(context='output', value='default'):
    """ Publish a message. """
    print('publish', value)
    yield session.publish(u'com.myapp.universal_feedback', {"id": context, "value": value})

@inlineCallbacks
def hub(thing):
    """ Main script. """
    do_things
    yield publish('output', 'some data for you')
    do_more_things
    yield publish('status', 'a progress message')
    do_even_more_things
    yield publish('status', 'some more data')
    do_all_the_things
    yield publish('other', 'something else')