如何在CherryPy独立的Web服务器上启动Bottle应用程序?

3

我有一个使用bottle框架开发的Python Web应用程序。我的bottle应用是Web API,提供返回JSON数据的方法,因此不需要静态内容。我正在尝试使用CherryPy服务器将其部署到生产环境中,该服务器应该非常适合生产应用程序。

我的web_api.py文件(我的bottle应用)大致如下:

from bottle import Bottle, request

app = Bottle()

@app.get('/stuff')
def do_stuff():
    '''
    Method that does stuff.
    '''
    stuff = {'data': 'some data'}
    # Return the environment info as Json data
    return stuff

我有一个server.py文件,用于在CherryPy服务器上启动Bottle应用程序,看起来像这样:

from my_package.web_api import app
from cherrypy.wsgiserver import CherryPyWSGIServer

server = CherryPyWSGIServer(
    ('0.0.0.0', 80),
    app,
    server_name='My_App',
    numthreads=30)

server.start()

所以当我使用这个命令运行我的服务器:

python server.py

我的服务器已经成功启动并且在80端口监听,但是一旦我启动了Web服务器,我就无法停止它了。我尝试过Ctrl + C,在开发服务器上起作用,但在这里没有任何效果。我是否正确地启动了服务器?一旦它运行起来,该如何停止它?这是使用CherryPy来启动Bottle应用程序的正确方法吗?

顺便说一下,我正在Windows 8上运行Python 2.7。


任何现在(2017年)查看此问题的人都应该知道,这在最近版本的CherryPy中不起作用。自9.0.0版本(2017年1月)以来,cherrypy.wsgiserver已移至Cheroot - OCarneiro
2个回答

10
您的代码是正确的,您只需要添加一个try/catch语句:
from my_package.web_api import app
from cherrypy.wsgiserver import CherryPyWSGIServer

server = CherryPyWSGIServer(
    ('0.0.0.0', 80),
    app,
    server_name='My_App',
    numthreads=30)

try:
    server.start()
except KeyboardInterrupt:
    server.stop()

你可能还想考虑使用 wsgi-request-logger 或类似的工具记录一些日志。

以下是三种在 cherrypy 中托管 WSGI 应用程序的替代方式:

import cherrypy as cp
from cherrypy.wsgiserver import CherryPyWSGIServer
from cherrypy.process.servers import ServerAdapter


from bottle import Bottle

app = Bottle()

@app.get('/stuff')
def do_stuff():
    '''
    Method that does stuff.
    '''
    stuff = {'data': 'some dataX'}
    return stuff

def run_decoupled(app, host='0.0.0.0', port=8080, **config):
    server = CherryPyWSGIServer((host, port), app, **config)
    try:
        server.start()
    except KeyboardInterrupt:
        server.stop()

def run_in_cp_tree(app, host='0.0.0.0', port=8080, **config):
    cp.tree.graft(app, '/')
    cp.config.update(config)
    cp.config.update({
        'server.socket_port': port,
        'server.socket_host': host
    })
    cp.engine.signals.subscribe() # optional
    cp.engine.start()
    cp.engine.block()

def run_with_adapter(app, host='0.0.0.0', port=8080, config=None, **kwargs):
    cp.server.unsubscribe()
    bind_addr = (host, port)
    cp.server = ServerAdapter(cp.engine,
                              CherryPyWSGIServer(bind_addr, app, **kwargs),
                              bind_addr).subscribe()
    if config:
        cp.config.update(config)
    cp.engine.signals.subscribe() # optional
    cp.engine.start()
    cp.engine.block()
run_in_cp_treerun_with_adapter 函数使用了 CherryPy 引擎,它可以使用插件,包括现成的自动重新加载、pidfile、守护进程、信号管理和一些其它好处,并且还可以自己创建插件。
请注意,您还可以使用WSGIPathInfoDispatcher将多个 wsgi 应用程序附加到 CherryPyWSGIServer 上。

1
哇!@cyraxjoe,你的回答太棒了,非常感谢!我花了一整天都没有找到这个信息。谢谢 :) - Cas
顺便问一下@cyraxjoe,你有没有在类似我这样的设置中使用wsgi-request-logger的示例?我在CherryPy上使用Bottle。我按照他们的文档操作,但是我的日志为空。 - Cas
2
@Cas 我刚刚写了一篇博客文章,详细阐述了访问/错误日志的用例。希望对你有所帮助。 - cyraxjoe
太赞了,伙计,你是最棒的! - Cas

0

在2019年,尝试将任何WSGI服务器连接到我的BottlePy应用程序中对于像我这样的新手来说非常棘手。我尝试连接了几个服务器,花费了大部分时间在CherryPy上,但它的语法已经改变了。

对我来说最简单的是waitress https://waitress.readthedocs.io/en/latest/usage.html。在我弄清楚如何在waitress上使用后,我也在cherrypy上使用了它。所以:

CherryPy http://docs.cherrypy.org/en/latest/advanced.html?highlight=WSGi#host-a-foreign-wsgi-application-in-cherrypy

1)在导入之后添加以下内容

import cherrypy as cp

app  = bottle.Bottle()

2) 将路由中的“@bottle”更改为“@app” 3) 将此添加为主函数
 cp.tree.graft(app, '/')
 cp.server.start()

服务员

1) 在导入后添加

import waitress 

app  = bottle.Bottle()

2) 将此添加为主函数

 waitress.serve(app, listen='*:44100')

3) 将路由中的"@bottle"更改为"@app"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接