カテゴリー
Uncategorized

[Python] custom urllib2 opener

from urllib2 import *
class MyHttpHandler(HTTPErrorProcessor):
#parent = OpenerDirector()
handler_order = 1
def http_request(self, request):
return request
https_request = http_request
def default_open(self, request):
"""return None for propagation"""
return None
def http_open(self, request):
"""return None for propagation"""
return None
https_open = http_open
def unknown_open(self, request):
"""return None for propagation"""
return None
def http_response(self, request, response):
response = self.parent.error('http', request, response, response.code,
response.msg, response.info())
return response
https_response = http_response
def http_error_default(self, request, fp, code, msg, headers):
"""return None for propagation"""
raise HTTPError(request.get_full_url(), code, msg, headers, fp)
def http_error_XXX(self, request, fp, code, msg, headers):
"""return None for propagation"""
return None
urlopen = build_opener(MyHttpHandler).open

build_opener はデフォルトで [ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor] を組み込む。これらの動作を変更したいならそのクラスから導出したクラスを引数に指定する。

ハンドラはマルチスレッドで呼ばれる可能性があるので self ではなく、request で状態を保持する。

メソッドの呼ばれる順

  • http_request
  • default_open
  • http_open
  • unknown_open
  • http_response

以下は HTTPErrorProcessor.http_response が呼ぶ

  • http_error_XXX
  • http_error_default

戻り値

*_request は request オブジェクトを必ず返さなければならない。

*_response は response オブジェクトを必ず返さなければならない。

他は assert(bool(result)) な値を返せばハンドラの伝搬は停止する。None を返すと他のハンドラが呼ばれる。例外は好きに投げろ。

割と良くできてると思います。またしても classic class ではありますが。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です