代码之家  ›  专栏  ›  技术社区  ›  DeepSpace

使用multiprocess.Pool同时运行2个瓶子应用程序

  •  0
  • DeepSpace  · 技术社区  · 7 年前

    我遇到的情况是,我需要同时运行两个应用程序(在不同的端口上)。我知道这可能不是最好的想法/设计,但请容忍我。

    主要问题是 bottle.run 这是阻塞。显而易见的解决办法是使用 multiprocessing.Pool ,但我想这不是很明显。

    from multiprocessing import Pool
    import bottle
    
    app = bottle.Bottle()
    
    @app.route('/')
    def index():
        return 'hi'
    
    
    def run_app(port):
        bottle.run(port=port)
    
    
    if __name__ == '__main__':
        pool = Pool(2)
    
        ps = [pool.apply_async(run_app, (port,))
              for port in (8081, 8082)]
    
        [p.get() for p in ps]  # YES, using a list comp for side-effect
    

    输出为

    Bottle v0.12.15 server starting up (using WSGIRefServer())...
    Listening on http://127.0.0.1:8081/
    Hit Ctrl-C to quit.
    
    Bottle v0.12.15 server starting up (using WSGIRefServer())...
    Listening on http://127.0.0.1:8082/
    Hit Ctrl-C to quit.
    

    然而,尝试使用两个不同的应用程序是行不通的。

    from multiprocessing import Pool
    import bottle
    
    app1 = bottle.Bottle()
    app2 = bottle.Bottle()
    apps = [app1, app2]
    
    
    @app1.route('/')
    def index_app1():
        return 'app1'
    
    
    @app2.route('/')
    def index_app2():
        return 'app2'
    
    
    def run_app(app, port):
        bottle.run(app, port=port)
    
    
    if __name__ == '__main__':
        pool = Pool(2)
    
        ps = [pool.apply_async(run_app, (app, port))
              for app, port in zip(apps, [8081, 8082])]
    
        [p.get() for p in ps]
    

    这个输出

    Traceback (most recent call last):
      File "test.py", line 29, in <module>
        [p.get() for p in ps]
      File "test.py", line 29, in <listcomp>
        [p.get() for p in ps]
      File "D:\Python37\Lib\multiprocessing\pool.py", line 657, in get
        raise self._value
      File "D:\Python37\Lib\multiprocessing\pool.py", line 431, in _handle_tasks
        put(task)
      File "D:\Python37\Lib\multiprocessing\connection.py", line 206, in send
        self._send_bytes(_ForkingPickler.dumps(obj))
      File "D:\Python37\Lib\multiprocessing\reduction.py", line 51, in dumps
        cls(buf, protocol).dump(obj)
    AttributeError: Can't pickle local object 'ConfigDict.__init__.<locals>.<lambda>'
    

    更新

    将第一个示例更改为:

    .
    .
    .
    
    def run_app(app, port):
        # instead of bottle.run(port=port) which uses default_app()
        app.run(port=port) # or bottle.run(app=app, port=port)
    .
    .
    .
    ps = [pool.apply_async(run_app, (app, port))
          for port in (8081, 8082)]
    

    也会导致相同的错误

    1 回复  |  直到 7 年前
        1
  •  0
  •   DeepSpace    7 年前

    解决这一问题的适当方法是使用 Bottle.mount

    import bottle
    
    parent_app = bottle.Bottle()
    child_app = bottle.Bottle()
    
    
    @parent_app.route('/')
    def index_app1():
        return 'parent_app'
    
    
    @child_app.route('/')
    def index_app2():
        return 'child_app'
    
    
    if __name__ == '__main__':
        parent_app.mount('/child_app/', child_app)
        parent_app.run()