Cherrypy中_cp_dispatch方法的异常行为问题
解决CherryPy中DispatchedFile1对象不可调用的TypeError问题
这个问题我之前也碰到过,本质是CherryPy对_cp_dispatch返回对象的处理规则没摸透~
问题根源
CherryPy通过_cp_dispatch拿到你返回的DispatchedFile1实例后,会按以下逻辑处理请求:
- 优先查找实例上**被
@cherrypy.expose装饰、且方法名与HTTP请求方法完全一致(大写)**的方法(比如GET()对应GET请求); - 如果找不到符合要求的方法,它会尝试把这个实例当作可调用对象直接执行;
- 而你的
DispatchedFile1类既没有正确暴露对应HTTP方法的处理函数,也没有实现__call__方法,所以就抛出了TypeError: 'DispatchedFile1' object is not callable这类异常。
解决方案
方案1:为类添加对应HTTP方法的暴露函数
这是最符合CherryPy设计规范的方式,直接在DispatchedFile1类中定义大写的HTTP方法,并加上@cherrypy.expose装饰器:
import cherrypy class DispatchedFile1: # 处理GET请求 @cherrypy.expose def GET(self, **kwargs): # 这里写你的GET请求逻辑,比如读取文件内容 return "处理GET请求:返回文件内容" # 处理POST请求 @cherrypy.expose def POST(self, **kwargs): # 这里写你的POST请求逻辑,比如上传文件 return "处理POST请求:上传文件成功" # 处理PUT请求 @cherrypy.expose def PUT(self, **kwargs): # 这里写你的PUT请求逻辑,比如更新文件 return "处理PUT请求:更新文件成功" # 处理DELETE请求 @cherrypy.expose def DELETE(self, **kwargs): # 这里写你的DELETE请求逻辑,比如删除文件 return "处理DELETE请求:删除文件成功" class Root: def _cp_dispatch(self, vpath): # 根据你的路由逻辑返回DispatchedFile1实例 # 比如匹配到特定路径时返回 return DispatchedFile1() if __name__ == "__main__": cherrypy.quickstart(Root())
方案2:让类实例可调用(统一处理所有HTTP方法)
如果你想在一个方法里统一处理所有HTTP请求,可以给DispatchedFile1类实现__call__方法,并确保它被@cherrypy.expose装饰:
import cherrypy class DispatchedFile1: @cherrypy.expose def __call__(self, **kwargs): # 获取当前请求的HTTP方法 current_method = cherrypy.request.method # 根据不同方法分支处理 if current_method == "GET": return "通过__call__处理GET请求" elif current_method == "POST": return "通过__call__处理POST请求" elif current_method == "PUT": return "通过__call__处理PUT请求" elif current_method == "DELETE": return "通过__call__处理DELETE请求" else: return "不支持的请求方法" class Root: def _cp_dispatch(self, vpath): return DispatchedFile1() if __name__ == "__main__": cherrypy.quickstart(Root())
关键注意事项
- 方法名必须是大写的
GET/POST/PUT/DELETE,小写的get不会被CherryPy识别; - 所有处理请求的方法必须加上
@cherrypy.expose装饰器,否则CherryPy会认为这是私有方法,不会用来处理请求; - 如果你的方法需要接收URL参数,建议加上
**kwargs来兼容所有可能的参数,避免参数不匹配导致的错误。
内容的提问来源于stack exchange,提问作者LittleByBlue
相关产品推荐
相关产品推荐

