运行 2 瓶应用程序同时使用 multiprocess.Pool
Running 2 bottle apps at the same time using multiprocess.Pool
我遇到了需要同时 运行 2 个应用程序(在不同的端口上)的情况。我知道这可能不是最好的 idea/design 但请耐心等待。
主要问题是bottle.run
阻塞了。明显的解决方法是使用 multiprocessing.Pool
,但我想它不是那么明显。
这有效(运行在 2 个不同的端口上运行相同的应用程序):
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.
但是,尝试使用 2 个不同的应用程序是行不通的。
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)]
也导致同样的错误
原来解决这个问题的合适方法是使用 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()
我遇到了需要同时 运行 2 个应用程序(在不同的端口上)的情况。我知道这可能不是最好的 idea/design 但请耐心等待。
主要问题是bottle.run
阻塞了。明显的解决方法是使用 multiprocessing.Pool
,但我想它不是那么明显。
这有效(运行在 2 个不同的端口上运行相同的应用程序):
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.
但是,尝试使用 2 个不同的应用程序是行不通的。
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)]
也导致同样的错误
原来解决这个问题的合适方法是使用 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()