Python urllib/urllib2 的簡單包裝

浮生若夢的程式設計發表於2017-12-11

初衷

最近有個專案,需要處理 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

相關文章