从类的继承看socketserver源码
当我们拿到一份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 应该结束了
从类的继承看socketserver源码的更多相关文章
- 解读python中SocketServer源码
在看SocketServer源码之前,先看一个例子: class Base(object): def __init__(self, name): self.name = name self.Testf ...
- python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)
python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...
- Python之socketserver源码分析
一.socketserver简介 socketserver是一个创建服务器的框架,封装了许多功能用来处理来自客户端的请求,简化了自己写服务端代码.比如说对于基本的套接字服务器(socket-based ...
- SocketServer源码学习(一)
SocketServer其实是对socket更高级的封装正如官网上说的:The socketserver module simplifies the task of writing network s ...
- 解读socketserver源码
解读python中SocketServer源码 再看继承 真正的大餐来之前,还是来点儿开胃菜!回顾一下关于类的继承的知识: 我们先看上面的代码,这是一个简单的类继承,我们可以看到父类Base和子 ...
- 文件上传下载、socketserver(并发)、解读socketserver源码
1.文件上传/下载 学习了socket套接字,我们现在可以写一个文件上传/下载的程序,如下示例: 分析上边代码,我们发现,client发送上传文件相关信息的字典序列化之后,server又给client ...
- socketserver源码解析和协程版socketserver
来,贴上一段代码让你仰慕一下欧socketserver的魅力,看欧怎么完美实现多并发的魅力 client import socket ip_port = ('127.0.0.1',8009) sk = ...
- socketserver 源码剖析:
socketserver 源码剖析[有图有真相]: (一).Socketserver 内部流程调用图: 详解: 1.self.RequestHandlerClass() = MyCla ...
- python day 15: IO多路复用,socketserver源码培析,
目录 python day 15 1. IO多路复用 2. socketserver源码分析 python day 15 2019/10/20 学习资料来自老男孩教育 1. IO多路复用 ''' I/ ...
随机推荐
- python 3.5 格式化字符串输出
#!/usr/bin/env python #encoding: utf-8 #.strip('里面可以去掉字符串中两边的字符') name = input('name :').strip(' ') ...
- 使用 ExpandableListView 实现折叠ListView
1:layout/expandablelistview_groups.xml 标题文件 <?xml version="1.0" encoding="utf-8&qu ...
- xdebug及webgrind的联用
参考URL: http://www.tuicool.com/articles/ERFNva http://blog.sina.com.cn/s/blog_635833b3010127q5.html h ...
- Qt在Windows下的三种编程环境搭建
尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/17363165 从QT官网可以得知其支持的平台.编译器 ...
- 【VC编程技巧】文件☞2.3CArchive的用法
CArchive 对象提供了一个类型安全缓冲机制CArchive 对象提供了一个类型安全缓冲机制.用于将可序列化对象写入CFile 对象或从中读取可序列化对象.通常,CFile 对象表示磁盘文件:但是 ...
- java开发经验分享(三)
三. 项目开发 1. 需求: 1) 需求最终需要开发人员在产品中实现,开发不合理的设计会浪费时间,开发技术无法实现的设计带来最大的痛苦:失败.所以,开发人员要重视需求以及需求评审,提出自己能够想到的所 ...
- C++ 中 struct和class 的区别
来自:http://hi.baidu.com/pengxiangbobin19890125/blog/item/b05586eee77300212df53411.html C++ prime 中 ...
- sizeof(long)
16位系统:long是4字节,int是2字节32位系统:long是4字节,int是4字节64位系统:long是8字节,int是4字节
- Windows系统结构
四种用户模式进程:1.系统支持进程,比如登录进程和会话管理器,并不是Windows服务,不有服务控制管理器启动2.服务进程,一些以Windows服务方式来运行的组件3.用户应用进程4.环境子系统服务器 ...
- 第29讲 UI组件之 ListView与 BaseAdapter,SimpleAdapter
第29讲 UI组件之 ListView与 BaseAdapter,SimpleAdapter 1.BaseAdapter BaseAdapter是Android应用程序中经常用到的基础数据适配器,它的 ...