阅读 145

Python urllib/urllib2 的简单包装

初衷

最近有个项目,需要处理 URL 地方很多,然 Python 的 url 处理库真是混乱不堪,我每次都是边看文档边写代码的。但是我自己很讨厌这种「边查文档边写代码」的方式,这种现象基本表示:要么是你对这门语言不熟悉,要么是这门语言(库)的 API 设计不怎么样。鉴于自己在大学的时候,就已经拿 Python 来写东西了,语言使用层面上的东西,已经很熟了,但是仍然每次都会陷入那种「边查边写」的境地,这应该是 API 设计出了问题(嗯,一定是这样的)。

怎么说呢,Python 标准库里面确实是有几个设计不佳的,API 命名混乱不堪(小写+缩写),而且要精读文档才能知晓全部意思。我理想中的 API 应该是见名知义的,库作者要充分理解调用者的感受,不应把自己的责任或义务转嫁到调用者身上。(不过说了那么多,人家的东西能进标准库就表示他 NB,爱用用,不用滚 :) )

历史原因也好,大牛牛逼也罢,都与我们没有关系,我们关心的是:快速且舒服优雅地解决问题。

接口包装

我们的项目还是使用 Python 2.7,自然面对的就是 urllib/urllib2/urlparse 这几个库。Python 3 里面将这一块相关的内容重新梳理了一下,API 什么的也变得清爽了很多。

我的简单包装如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

"""对urllib/urllib2标准库的封装"""

from __future__ import (absolute_import, unicode_literals)

import urlparse
import urllib


class UrlUtils(object):
    """处理URL的工具函数"""

    @classmethod
    def remove_fragment(cls, urlstr):
        return urlparse.urldefrag(urlstr)

    @classmethod
    def encode_special_chars(cls, query_str_value):
        return urllib.quote(query_str_value)

    @classmethod
    def decode_special_chars(cls, encoded_chars):
        return urllib.unquote(encoded_chars)

    @classmethod
    def encode_query_dict(cls, query_dict):
        return urllib.urlencode(query_dict)

    @classmethod
    def decode_query_dict(cls, encoded_dict):
        return urlparse.parse_qs(encoded_dict)

    @classmethod
    def get_url_instance(cls, urlstr):
        return urlparse.urlparse(urlstr, allow_fragments=True)
复制代码

由于我写 API 一般是「按需写,用到的时候才写」,并且「喜欢从原型代码里面提炼出接口,不太喜欢一开始就设计一个宏伟的蓝图」(能力不行,做不到),所以一般接口的数量也很少。

总结

如前文所述,Python 标准库里面确实有设计烂的地方,这一点需要承认。一般来说,如果一个接口在你需要反复翻阅文档才知道如何使用,那这就是你包装一下方便自己的时候了。

附录

  • Python 2 标准库文档
  • Python 3 标准库文档
  • Qt API design
关注下面的标签,发现更多相似文章
评论