您的位置:首页 > 其它

从类的继承看socketserver源码

2016-07-16 07:55 183 查看
当我们拿到一份python源代码,我们要怎么去看呢?下面我们以socketserver为例,看下面的一段代码:
#!/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

应该结束了





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: