gevent 提供了一个后门server,可以用来debug正在运行的进程,官方文档是这样描述的
The BackdoorServer provides a REPL inside a running process. As long as the process is monkey-patched, the BackdoorServer can coexist with other elements of the process.
下面这个例子是从stackoverflow 上看到的,这里自己实践一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import json from gevent import pywsgi from gevent import monkey from gevent import event from gevent.backdoor import BackdoorServer import time monkey.patch_all() a = "foo" def build_response(response): return json.dumps(response) def start_process(environ, start_response): ''' {"content": {"code": 0, "req_id": "20160420154445000"}, "res": "ok", "err_code": 0} ''' risk_id = 0 response = dict() response = { 'err_code': 0, 'res': 'ok', 'content': dict() } status = '200 OK' response_headers = [('Content-type', 'text/html'), ('Connection', 'close')] start_response(status, response_headers) return build_response(response) def main(): stop_event = event.Event() servers = [BackdoorServer(('127.0.0.1', 5001), banner="Hello from gevent backdoor!", locals={'foo': "From defined scope!"}), pywsgi.WSGIServer(('127.0.0.1', 5002), start_process, ), ] for server in servers: if not server.started: server.start() stop_event.wait() for server in servers: if server.started: server.stop() if __name__ == '__main__': main()
将这个python文件run起来,然后执行telnet 127.0.0.1 5001就可以链接到上面的进程中去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # telnet 127.0.0.1 5001> >> import greenlet, inspect# 获取当前协程> >> greenlet.getcurrent() <_Greenlet_stdreplace at 0x10bd40448: _handle_and_close_when_done(<bound method BackdoorServer.handle of <BackdoorSe, <bound method StreamServer.do_close of <BackdoorSe, (<gevent._socket3.socket object, fd=8, family=2, t)> # 获取当前协程的父协程,看到是hub,这其实是gevent的调度协程> >> greenlet.getcurrent().parent <Hub '' at 0x10bcdd6d8 select default pending=0 ref=2 resolver=<gevent.resolver_thread.Resolver at 0x10bd167f0 pool=<ThreadPool at 0x10bd169b0 0/1/10 hub=<Hub at 0x10bcdd6d8 thread_ident=0x140736039191424>>> threadpool=<ThreadPool at 0x10bd169b0 0/1/10 hub=<Hub at 0x10bcdd6d8 thread_ident=0x140736039191424>> thread_ident=0x7fffa99f8380> # 再网上走一层,这里就到了我们运行main的协程> >> inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)[FrameInfo(frame=<frame object at 0x7faecf476e48>, filename='xxxxxxxxxx', lineno=100, function='main', code_context=[' stop_event.wait()\n'], index=0), FrameInfo(frame=<frame object at 0x7faecf41ea78>, filename='xxxxxxxxxxx', lineno=107, function='<module>', code_context=[' main()\n'], index=0)] > >> inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)[1][0]<frame object at 0x7faecf41ea78> # 通过inspect可以获取变量a的值,这样就可以debug当前的进程了> >> inspect.getargvalues(inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)[1][0]).locals['a']'foo'