CherryPy的KeyError服务静态文件的WSGIServer

时间:2015-03-30 20:58:46

标签: python python-2.7 cherrypy

我正在尝试使用CherryPy的WSGI服务器来提供静态文件,例如Using Flask with CherryPy to serve static files。接受的答案的选项2看起来与我想要做的完全一样,但是当我尝试使用静态目录处理程序时,我得到KeyError

我尝试了什么:

>>>> import cherrypy
>>>> from cherrypy import wsgiserver
>>>> import os
>>>> static_handler = cherrypy.tools.staticdir.handler(section='/', dir=os.path.abspath('server_files')
>>>> d = wsgiserver.WSGIPathInfoDispatcher({'/': static_handler})
>>>> server = wsgiserver.CherryPyWSGIServer(('localhost', 12345), d)
>>>> server.start()

然后,当我尝试访问服务器时,我收到500响应并在控制台中出现以下错误:

KeyError('tools',)
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1353, in communicate
    req.respond()
  File "/Library/Python/2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 868, in respond
    self.server.gateway(self).respond()
  File "/Library/Python/2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 2267, in respond
    response = self.req.server.wsgi_app(self.env, self.start_response)
  File "/Library/Python/2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 2477, in __call__
    return app(environ, start_response)
  File "/Library/Python/2.7/site-packages/cherrypy/_cptools.py", line 175, in handle_func
    handled = self.callable(*args, **self._merged_args(kwargs))
  File "/Library/Python/2.7/site-packages/cherrypy/_cptools.py", line 102, in _merged_args
    tm = cherrypy.serving.request.toolmaps[self.namespace]
KeyError: 'tools'

每次尝试点击服务器应该能够显示的内容时,会显示两次。当我将Flask应用程序连接到服务器时,Flask应用程序按预期工作,但静态文件服务仍然提供相同的错误。

我需要做些什么才能让staticdir.handler正常工作?

1 个答案:

答案 0 :(得分:1)

我已经尝试了各种方法让它工作起来,直到今天也遇到了你一直看到的KeyError(以及其他问题)。

我终于设法让CherryPy通过调整this gist(包含在下面)中的代码来与Django应用程序一起提供静态服务。

import os
import cherrypy
from cherrypy import wsgiserver

from my_wsgi_app import wsgi

PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'public'))


class Root(object):
    pass

def make_static_config(static_dir_name):
    """
    All custom static configurations are set here, since most are common, it
    makes sense to generate them just once.
    """
    static_path = os.path.join('/', static_dir_name)
    path = os.path.join(PATH, static_dir_name)
    configuration = {static_path: {
        'tools.staticdir.on': True,
        'tools.staticdir.dir': path}
    }
    print configuration
    return cherrypy.tree.mount(Root(), '/', config=configuration)

# Assuming your app has media on diferent paths, like 'c', 'i' and 'j'
application = wsgiserver.WSGIPathInfoDispatcher({
    '/': wsgi.application,
    '/c': make_static_config('c'),
    '/j': make_static_config('j'),
    '/i': make_static_config('i')})

server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8070), application,
                                       server_name='www.cherrypy.example')
try:
    server.start()
except KeyboardInterrupt:
    print "Terminating server..."
    server.stop()

希望包装Flask应用程序非常相似。

我的关键是在虚拟类上使用cherrypy.tree.mount,而不是直接尝试使用staticdir.handler。

对于好奇 - 我使用gist中的代码来自定义django-cherrypy的runcpserver管理命令的版本,虽然事后看来从头开始创建新命令可能更容易。

祝你好运(感谢Alfredo Deza)!