【小ネタ】HTTP Status CodeによってPython2.7のurllib2.urlopenがどういう挙動になるか調べてみた

2015.11.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

サーモン大好き、横山です。

Python2.7 の urllib2.urlopen を使った際、HTTP Status Codeが300番台、400番台、500番台が返って来た時、Exceptionが吐かれるのか正常動作になるのか気になったので、調べてみました。

検証コード

今回任意のHTTP Status Codeを返してくれるサーバとして、 Test HTTP Status Codes さんを使いました。

http://status.savanttools.com/?code=[返して欲しいHTTP Status Code] にGETでアクセスすることで、任意のHTTP Status Codeのレスポンスを得る事が出来ます。

今回、 Test HTTP Status Codes さんに書いてあるステータスコードを一通りスクリプトから叩いて確認しました。

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

from __future__ import print_function
import urllib
import urllib2


status_codes = []
status_codes.extend([100 + i for i in range(3)]) 
status_codes.extend([200 + i for i in range(9)]) 
status_codes.extend([226]) 
status_codes.extend([300 + i for i in range(9)]) 
status_codes.extend([400 + i for i in range(27)]) 
status_codes.extend([428, 429, 431, 444, 449, 450, 499]) 
status_codes.extend([500 + i for i in range(11)]) 

proc_codes = []
raise_codes = []
for code in status_codes:
    try:
        resp = urllib2.urlopen('http://status.savanttools.com/?' + urllib.urlencode({'code': code}))
        proc_codes.append(code)
    except urllib2.HTTPError, e:
        raise_codes.append(code)


print(', '.join(['{}'.format(code) for code in proc_codes]))
print('-' * 30)
print(', '.join(['{}'.format(code) for code in raise_codes]))

実行結果

100番と200番台以外のHTTP Status Codeはraiseされるらしいです。

100, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226
------------------------------
101, 102, 300, 301, 302, 303, 304, 305, 306, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 428, 429, 431, 444, 449, 450, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510

まとめ

200番台以外は urllib2.HTTPError が出ると思っていたほうが良さそうです。

ただ、 urllib2のドキュメント を見ると多数Handlerが用意されており、それを直接、または継承したオブジェクトを urllib2.urlopen に渡す事によってより細かい挙動を設定することが可能のようです。