技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 源码分析 --> urllib2源码解读二(简单的urlopen)

urllib2源码解读二(简单的urlopen)

浏览:1624次  出处信息

对上面的几个对象有个基本概念之后,再来深究下代码,从一个最普通的urllib2.urlopen()开始,先来熟悉下第一个重点对象:build_opener这个函数。

大家最为熟悉的一段代码:

res = urllib2.urlopen('http://python.org')

这端代码的作用就是打开http://python.org这个网站,返回一个response对象。

下面咱们来深入到这个urlopen函数中,来看下代码:

def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):

   """

   对外的访问函数

   """


   global _opener

   if _opener is None:
       _opener = build_opener()
   return _opener.open(url, data, timeout)

在程序第一次执行urlopen操作的时候,其实就是构建了一个全局的_opener对象,然后用这个_opener对象来处理url以及data。这样做的好处就是如果你在程序中要多次调用urlopen,就不会频繁构建opener对象了。当然这个opener也不是一次加载就再也不可变了,urllib2提供了install_opener这个方法,你可以在客户端调用build_opener然后用前面的那个install_opener来加载。

这段代码很简单,起作用就是构建一个opener对象,所以咱来看下它是如何构建这个_opener对象的。

不过在此之前需要先了解下我们一直在说的opener是什么?

这个_opener其实就是OpenerDirector的一个实例,OpenerDirector上篇已经大概说了,目前我们需要了解的就是在这个对象中定义了几个字典属性,这些字典就是用来存放对应的handler的。

      self.handlers = []  

       # manage the individual handlers

       self.handle_open = {}

       self.handle_error = {}

       self.process_response = {}

       self.process_request = {}

最主要的三个字典是process_request、handle_open、process_response,分别存放处理request、打开request、处理response的handler。

所谓的handler是什么呢?顾名思义,就是处理器,目前只需要知道有一群handler,分别用来处理不同的对象,然后对应的处理结果。

有了这样的认识我们先来看下build_opener()函数是如何来构建这个OpenerDirector对象的。

def build_opener(*handlers):

   import types

   def isclass(obj):

       return isinstance(obj, (types.ClassType, type))



   opener = OpenerDirector()

   #这里定义了一系列的handler类

   default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,

                      HTTPDefaultErrorHandler, HTTPRedirectHandler,

                      FTPHandler, FileHandler, HTTPErrorProcessor]

   if hasattr(httplib, 'HTTPS'):#判断是否支持https

       default_classes.append(HTTPSHandler)

   skip = set()

   for klass in default_classes:

       #处理用户函数参数handler中是否有相同的类在默认类中。

       for check in handlers:

           if isclass(check):

               if issubclass(check, klass):

                   skip.add(klass)

           elif isinstance(check, klass):

               skip.add(klass)

   for klass in skip:

       default_classes.remove(klass)

   #这一步,将默认的类实例化之后加入opener中

   for klass in default_classes:

       opener.add_handler(klass())

   #然后把参数中的handler类实例化,加到OpenerDirector中。

   for h in handlers:

       if isclass(h):

           h = h()

       opener.add_handler(h)

   return opener

这个函数的整个过程其实相对简单,只是把系统默认的handler和用户传入的自定义handler参数进行了对比弃重。最后把所有的handler都实例化通过opener.add_handler方法添加给OpenerDirector。最后返回构建好的OpenerDirector实例。

关于这个build_opener就先说到这里,下篇再来说OpenerDirector的add_handler的具体流程。

另外,最近一直在思考一个问题,如何把这些(我学到的东西,比如urllib2)东西能够更好的,更清晰易懂的让读者明白。自己理解urllib2的源码不难,难的是以何种方式或者说何种组织结构来写能让人更容易懂。不知道各位有没有什么好的建议或者好的书籍推荐。

目前我自己的想法就是尽量让每篇文章涉及的未知知识点少,每篇文章也尽量内容单一,这样读起来会不会容易些?

建议继续学习:

  1. urllib2源码解读一(开篇)    (阅读:2773)
  2. urllib2源码解读三(探索OpenerDirector的add_handler)    (阅读:1505)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1