给cherrypy 打gevent WSGIServer的patch

1. patch Serving 类

2. 关闭python的原生WSGIServer

具体使用例子参考 我的开源项目  https://github.com/thomashuang/Lilac

#!/usr/bin/env python

import cherrypy
from cherrypy import _cprequest
from cherrypy.lib import httputil
import sys
import logging
from cherrypy.process import servers LOGGER = logging.getLogger('web.patch') try:
from greenlet import getcurrent as get_ident
except ImportError:
LOGGER.ERROR('You shall install Gevent, if wanna use gevent wsgi server')
exit(1) def patch_cherrypy():
cherrypy.serving = GreenletServing() class GreenletServing(object):
__slots__ = ('__local__', ) def __init__(self):
object.__setattr__(self, '__local__', {})
ident = get_ident()
self.__local__[ident] = {
'request': _cprequest.Request(httputil.Host("127.0.0.1", 80), httputil.Host("127.0.0.1", 1111)),
'response': _cprequest.Response()
} def load(self, request, response):
self.__local__[get_ident()] = {
'request': request,
'response': response
} def __getattr__(self, name):
try:
return self.__local__[get_ident()][name]
except KeyError:
raise AttributeError(name) def __setattr__(self, name, value):
ident = get_ident()
local = self.__local__
try:
local[ident][name] = value
except KeyError:
local[ident] = {name: value} def clear(self):
"""Clear all attributes of the current greenlet."""
del self.__local__[get_ident()]
#!/usr/bin/env python

import cherrypy
import sys
import logging
from cherrypy.process import servers LOGGER = logging.getLogger('web.server') class GeventWSGIServer(object): """Adapter for a gevent.wsgi.WSGIServer.""" def __init__(self, *args, **kwargs):
from lilac.web.patch import patch_cherrypy patch_cherrypy()
self.args = args
self.kwargs = kwargs
self.ready = False def start(self):
"""Start the GeventWSGIServer."""
# We have to instantiate the server class here because its __init__
from gevent.wsgi import WSGIServer self.ready = True
LOGGER.debug('Starting Gevent WSGI Server...')
self.httpd = WSGIServer(*self.args, **self.kwargs)
self.httpd.serve_forever() def stop(self):
"""Stop the HTTP server."""
LOGGER.debug('Stoping Gevent WSGI Server...')
self.ready = False
self.httpd.stop() class WebServer(object): def __init__(self, server_name='Sola', host='127.0.0.1', port=8080, use_gevent=True, debug=False, encoding='UTF-8'):
self.server_name = server_name
self.host = host
self.port = port
self.debug = debug
self.encoding = encoding
self.use_gevent = use_gevent
self.config = self.gen_config()
self.bootstrap() def bootstrap(self):
"""You can intialize more configs or settings in here"""
pass def gen_config(self):
conf = {
'global':
{
'server.socket_host': self.host,
'server.socket_port': self.port,
'engine.autoreload.on': self.debug,
#'log.screen': self.debug,
'log.error_file': '',
'log.access_file': '',
'request.error_response': self.handle_internal_exception,
'tools.decode.on': True,
"tools.encode.on": True,
'tools.encode.encoding': self.encoding,
'tools.gzip.on': True,
'tools.log_headers.on': False,
'request.show_tracebacks': False,
}
}
if self.use_gevent:
conf['global']['environment'] = 'embedded' return conf def set_404_pape(self, not_found_handler):
"""Custom not found page"""
self.config['global']['error_page.404'] = not_found_handler def asset(self, path, asset_path):
"""Set servering Static directory"""
self.config[path] = {
'tools.staticdir.on': True,
'tools.staticdir.dir': asset_path
} def handle_internal_exception(self):
"""Handle the unknow exception and also throw 5xx status and push message to frontend"""
cls, e, tb = sys.exc_info() LOGGER.exception('Unhandled Error %s', e)
resp = cherrypy.response
resp.status = 500
resp.content_type = 'text/html; charset=UTF-8' if cherrypy.request.method != 'HEAD':
resp.body = ["""<html>
<head><title>Internal Server Error </title></head>
<body><p>An error occurred: <b>%s</b></p></body>
</html> """ % (str(e))] def new_route(self):
return cherrypy.dispatch.RoutesDispatcher() def create_app(self):
raise NotImplemented('Must implement create_app in Subclass') def _bootstrap_app(self):
ctl, routes = self.create_app()
cherrypy.config.clear()
config = {'/': {'request.dispatch': routes}, 'global': self.config}
config.update(self.config)
cherrypy.config.update(config)
return cherrypy.tree.mount(ctl, '/', config) def serve_forever(self):
engine = cherrypy.engine
if hasattr(engine, "signal_handler"):
engine.signal_handler.subscribe()
if hasattr(engine, "console_control_handler"):
engine.console_control_handler.subscribe()
app = self._bootstrap_app()
try:
if self.use_gevent:
# Turn off autoreload when using *cgi.
#cherrypy.config.update({'engine.autoreload_on': False})
addr = cherrypy.server.bind_addr
cherrypy.server.unsubscribe()
f = GeventWSGIServer(addr, app, log=None)
s = servers.ServerAdapter(engine, httpserver=f, bind_addr=addr)
s.subscribe()
engine.start()
else:
cherrypy.quickstart(app)
except KeyboardInterrupt:
self.stop()
else:
engine.block() def stop(self):
cherrypy.engine.stop()

cherrypy & gevent patch的更多相关文章

  1. 高并发异步uwsgi+web.py+gevent

    为什么用web.py? python的web框架有很多,比如webpy.flask.bottle等,但是为什么我们选了webpy呢?想了好久,未果,硬要给解释,我想可能原因有两个:第一个是兄弟项目组用 ...

  2. 协程--gevent模块(单线程高并发)

    先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行.这种 ...

  3. [转载]python gevent

    原地址: http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001407503089 ...

  4. 流动python - 写port扫描仪和各种并发尝试(多线程/多进程/gevent/futures)

    port扫描仪的原理非常easy.没有什么比操作更socket,能够connect它认为,port打开. import socket def scan(port): s = socket.socket ...

  5. gevent拾遗

      在前文已经介绍过了gevent的调度流程,本文介绍gevent一些重要的模块,包括Timeout,Event\AsynResult, Semphore, socket patch,这些模块都涉及当 ...

  6. Python并发编程协程(Coroutine)之Gevent

    Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...

  7. gevent程序员指南

    gevent程序员指南 由Gevent社区编写 gevent是一个基于libev的并发库.它为各种并发和网络相关的任务提供了整洁的API.   介绍 本指南假定读者有中级Python水平,但不要求有其 ...

  8. python中的猴子补丁Monkey Patch

    python中的猴子补丁Monkey Patch 什么是猴子补丁 the term monkey patch only refers to dynamic modifications of a cla ...

  9. 协程----greenlet模块,gevent模块

    1.协程初识,greenlet模块 2.gevent模块(需要pip安装) 一.协程初识,greenlet模块: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线 ...

随机推荐

  1. 洛谷 P2158 [SDOI2008]仪仗队 && 洛谷 P1447 [NOI2010]能量采集

    https://www.luogu.org/problemnew/show/P2158 以人所在位置为(0,0)建立坐标系, 显然除了(0,1)和(1,0)外,可以只在坐标(x,y)的gcd(x,y) ...

  2. Lucky Array Codeforces - 121E && Bear and Bad Powers of 42 Codeforces - 679E

    http://codeforces.com/contest/121/problem/E 话说这题貌似暴力可A啊... 正解是想出来了,结果重构代码,调了不知道多久才A 错误记录: 1.线段树搞混num ...

  3. Stars in Your Window POJ - 2482

    错误记录: 题目说输入在int范围内,但是运算过程中可能超int:后来开了很多longlong就过了 #include<cstdio> #include<algorithm> ...

  4. git简单使用方法

    跟远程库关联起来: http://www.cnblogs.com/Gabriel-Wei/p/6564102.html http://www.liaoxuefeng.com/wiki/00137395 ...

  5. HAL之PWM

    PWM是定时器的一个输出功能,要分配在有对应输出的管脚上.分频和定时值决定了周期,捕获寄存器的值就是占空比,当计数寄存器的值小于捕获值时输出固定电平(H),当大于时翻转电平,当计数器值溢出时将重载值载 ...

  6. RedHat改yum源免费使用CentOS源

    linux默认是安装了yum软件的,但是由于激活认证的原因让redhat无法直接进行yum安装一些软件 如果我们需要在redhat下直接yum安装软件,我们只用把yum的源修改成CentOS的就好了, ...

  7. gbk编码文件传输json实例

    cline.php <?php $str='此地无银三百两'; $str = iconv('gbk', 'utf-8', $str); //Json只支持utf-8编码,如果不进行转码的话,服务 ...

  8. JAVA 运用流编程实现简单的"记事本"功能

    一.概要 1.功能介绍 2.实现的思路及步骤代码 3.完整代码 二.功能 运用IO流和Swing实现简单的记事本功能(打开.保存.退出) 三.思路及实现步骤 1.在构造函数中画出操作界面 //创建jt ...

  9. hihocoder1067 最近公共祖先·二

    思路: 使用tarjan算法,这是一种离线算法. 实现: #include <bits/stdc++.h> using namespace std; typedef pair<int ...

  10. <meta>详解

    一.元数据和<meta> 元数据是描述以提供关于其他数据的数据,在<meta>中,html document是被描述的数据,meta标签中包括的数据是描述html docume ...