从类的继承看socketserver源码
2016-07-16 07:55
183 查看
当我们拿到一份python源代码,我们要怎么去看呢?下面我们以socketserver为例,看下面的一段代码:
反回看BaseSever的代码,代码里就定义了self.process_request()方法,那么实际是执行这个方法么?
我们从这里可以看出,得先看下
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author: ZCX import socketserver #导入socketserver模块 class MyServer(socketserver.BaseRequestHandler): #定义一个类 def handle(self): #定义自己的handle方法 pass if __name__ == '__main__': obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyServer) #传递参数 obj.serve_forever() #运行这段代码的意思是运行一个自定义的服务器,而handle方法是socket传递自定义信息,这里我们暂时不论需要传递什么,当我们拿到这么一段代码,如何深入查看呢?从执行的顺序来看,当执行上面的代码时,会执行
obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyServer) #传递参数 这里传了两个参数,一个是('127.0.0.1', 9999),一个是自定义的MyServer类,所以我们就得追寻到底是哪个方法调用了传入的参数呢? 先来点小知识,类的继承关系是,当子类中没有相应的方法时就会去父类中寻找,当继承多个父类时,子类没有的,依继承顺序,在父类中由左到右依次查询,为了查参,我们先看下ThreadingTCPServer
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass 源码里直接pass了,不过它继承了两个类:
ThreadingMixIn, TCPServer 我们先看ThreadingMixIn
class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the # main process daemon_threads = False def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. In addition, exception handling is done here. """ try: self.finish_request(request, client_address) self.shutdown_request(request) except: self.handle_error(request, client_address) self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request.""" t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()有两个方法,但是不是我们想要的啊,FCUK...然后只能再去看看TCPServer,
class TCPServer(BaseServer): """Base class for various socket-based server classes. Defaults to synchronous IP stream (i.e., TCP). Methods for the caller: - __init__(server_address, RequestHandlerClass, bind_and_activate=True) - serve_forever(poll_interval=0.5) - shutdown() - handle_request() # if you don't use serve_forever() - fileno() -> int # for selector Methods that may be overridden: - server_bind() - server_activate() - get_request() -> request, client_address - handle_timeout() - verify_request(request, client_address) - process_request(request, client_address) - shutdown_request(request) - close_request(request) - handle_error() Methods for derived classes: - finish_request(request, client_address) Class variables that may be overridden by derived classes or instances: - timeout - address_family - socket_type - request_queue_size (only for stream sockets) - allow_reuse_address Instance variables: - server_address - RequestHandlerClass - socket """ address_family = socket.AF_INET socket_type = socket.SOCK_STREAM request_queue_size = 5 allow_reuse_address = False def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise def server_bind(self): """Called by constructor to bind the socket. May be overridden. """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() def server_activate(self): """Called by constructor to activate the server. May be overridden. """ self.socket.listen(self.request_queue_size) def server_close(self): """Called to clean-up the server. May be overridden. """ self.socket.close() def fileno(self): """Return socket file number. Interface required by selector. """ return self.socket.fileno() def get_request(self): """Get the request and client address from the socket. May be overridden. """ return self.socket.accept() def shutdown_request(self, request): """Called to shutdown and close an individual request.""" try: #explicitly shutdown. socket.close() merely releases #the socket and waits for GC to perform the actual close. request.shutdown(socket.SHUT_WR) except OSError: pass #some platforms may raise ENOTCONN here self.close_request(request) def close_request(self, request): """Called to clean up an individual request.""" request.close()我们看到它接收到了一个server_address,和RequestHandlerClass,所以obj接收的参数到了这里,我们再看它的接收方法,重建了__init__方法
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise那么
BaseServer.__init__(self, server_address, RequestHandlerClass)接收是要从哪里看呢?server_address, RequestHandlerClass 紧接着我看到,重定义的__init__()方法执行了BaseServer.__init__()的方法,那么实际上就是去BaseServer,执行了BaseServer__init__()方法
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) 接着我们再去看BaseServer__init__()方法,
BaseServer
摘录出来以下的__init__()方法 def __init__(self, server_address, RequestHandlerClass): """Constructor. May be extended, do not override.""" self.server_address = server_address self.RequestHandlerClass = RequestHandlerClass self.__is_shut_down = threading.Event() self.__shutdown_request = False 从这里看再从整体上看可以看出来,self.RequestHandlerClass其实就是我们最初定义的类=>MyServer. 到这里应该没有什么大问题,server_address就是我们传出的IP加端口 然后我们再看下一句
obj.serve_forever() 执行了serve_forever()方法
def serve_forever(self, poll_interval=0.5): """Handle one request at a time until shutdown. Polls for shutdown every poll_interval seconds. Ignores self.timeout. If you need to do periodic tasks, do them in another thread. """ self.__is_shut_down.clear() try: # XXX: Consider using another file descriptor or connecting to the # socket to wake this up instead of polling. Polling reduces our # responsiveness to a shutdown request and wastes cpu at all other # times. with _ServerSelector() as selector: selector.register(self, selectors.EVENT_READ) while not self.__shutdown_request: ready = selector.select(poll_interval) if ready: self._handle_request_noblock() self.service_actions() finally: self.__shutdown_request = False self.__is_shut_down.set()看源代码可以看到,if ready: self._handle_request_noblock()也就是说,成功的话执行的就是self._handle_request_noblock()方法,然后我们再去看_handle_request_noblock()方法,
def _handle_request_noblock(self): """Handle one request, without blocking. I assume that selector.select() has returned that the socket is readable before this function was called, so there should be no risk of blocking in get_request(). """ try: request, client_address = self.get_request() except OSError: return if self.verify_request(request, client_address): try: self.process_request(request, client_address) except: self.handle_error(request, client_address) self.shutdown_request(request) else: self.shutdown_request(request)第一个try是接收客户端的数据,第二个try是处理的方法,那么我们看到执行了
self.process_request()方法
反回看BaseSever的代码,代码里就定义了self.process_request()方法,那么实际是执行这个方法么?
我们回头看,类的继承关系是,当子类中没有相应的方法时就会去父类中寻找,当继承多个父类时,子类没有的,依继承顺序,在父类中由左到右依次查询 ThreadingTCPServer
1 class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
我们从这里可以看出,得先看下
ThreadingMixIn
我记得里面也有一个self.process_request()方法哦
class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the # main process daemon_threads = False def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. In addition, exception handling is done here. """ try: self.finish_request(request, client_address) self.shutdown_request(request) except: self.handle_error(request, client_address) self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request.""" t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()看到了吧,哈哈,这下再也不会怕看源代码了吧最后两步,从上面一看就知道执行
process_request_thread 最后是
self.finish_request 应该结束了
相关文章推荐
- 单元格删除方法和交换位置方法
- BZOJ 2115 [Wc2011] Xor
- PHP中exit()与die()的区别
- FMDB的简单应用
- Android中Recyclerview使用5----添加头部:RecyclerViewHeader
- PHP反射(ReflectionClass、ReflectionMethod)在ThinkPHP框架的控制器调度模块中的应用
- 透过统计力学,模拟软物质——EPJE专访2016年玻尔兹曼奖得主Daan Frenkel
- 根据输入的textField首字符排序
- PHP反射ReflectionClass、ReflectionMethod 入门教程
- Android中Recyclerview使用4----选中某一条目
- bzoj 1823 [JSOI2010]满汉全席
- 【教训】 form表单提交时,action url中参数无效
- runLoop机制
- uboot 命令分析(一) — bootm
- 图像和链接 、 表格 、 列表
- 性别显示
- 欧几里得最大公约数两种算法
- 简单的block页面传值
- Uboot与Linux之间的参数传递
- 绘制图画