Six: Python 2 と 3 の互換性ライブラリ

Sixは、Python 2 と Python 3 の間の違いを吸収するためのシンプルなユーティリティを提供します。それらは、Python 2 と Python 3 の両方でコードベースの変更なく動作することをサポートするよう意図されています。six はたった一つの Python ファイルだけで構成されていますから、プロジェクトへコピーして利用することに苦痛はありません。

Six は PyPi からダウンロード出来ます。バグトラッカーとソースコード管理は BitBucket にあります。

命名「six」は、これは 2*3 が 6 であることから来ています。なぜ足さないかって? 掛け算はより足し算より強いからさ、いや…どのみち “five” は既に (ご存知の通り死にかけの)Zope Five プロジェクトによって奪われてますから。

Indices and tables

Package contents

six.PY2

Python 2 で動作しているかどうかを示す真偽値です。

six.PY3

Python 3 で動作しているかどうかを示す真偽値です。

Constants

Sixは、Python のバージョン間で異なりうる定数群を提供します。これらのうち _types で終わるものが最も有用で、それらは isinstanceissubclass の第2引数として引き渡すことが出来ます。

six.class_types

class 型となりうる types です。Python 2 においては、これは旧スタイル・新スタイル class両方の意味になり、Python 3 においては単に新スタイル class です。

six.integer_types

整数型となりうる types です。Python 2 においては、これは longint の場合がありますが、Python 3 においては int のみです。

six.string_types

文字列データ型となりうる types です。Python 2 の basestring() に対し、Python 3 では str です。

six.text_type

文字列(Unicode)を表現するデータ型です。Python 2 の unicode() に対し、Python 3 では str です。

six.binary_type

バイナリを表現するデータ型です。Python 2 の str に対し、Python 3 では bytes です。

six.MAXSIZE

listdict のようなコンテナの最大サイズです。これは (3.x を含む)Python 2.6 以降には含まれる sys.maxsize と等価です。ただし、Python 2 の sys.maxint に似ているからと飛びついてはなりません。同じではありません。Python 3 には sys.maxint に直接対応するものはありません。というのも、Python 3 においては、整数型には、メモリの許す限りの上限しかないのです。

使用例を示しておきます:

import six

def dispatch_types(value):
    if isinstance(value, six.integer_types):
        handle_integer(value)
    elif isinstance(value, six.class_types):
        handle_class(value)
    elif isinstance(value, six.string_types):
        handle_string(value)

Object model compatibility

Python 3 では、インタプリタのデータ構造についていくつか、属性名の変更がありました。以下に続くアクセッサが利用可能です。なお、関数・メソッドについて inspect するのに推奨される方法は、標準ライブラリの inspect モジュールを使うことです。

six.get_unbound_function(meth)

meth を非結合メソッド (unbound method) ではない関数として取り出します。Python 3 には 非結合メソッド (unbound method) はないため、この場合、 meth そのものを返します。このように使います:

from six import get_unbound_function

class X(object):
    def method(self):
        pass
method_function = get_unbound_function(X.method)
six.get_method_function(meth)

meth を method オブジェクトでない関数として取り出します。

six.get_method_self(meth)

結合メソッド (bound method) の self を取り出します。

six.get_function_closure(func)

func に関連付いたクロージャ(セルのリストです)を取り出します。これは Python 2.6+ における func.__closure__ 、Python 2.5 における func.func_closure と同じです。

six.get_function_code(func)

func に関連付いた code オブジェクトを取り出します。これは Python 2.6+ における func.__code__ 、Python 2.5 における func.func_code と同じです。

six.get_function_defaults(func)

func に関連付いた規定のタプルを取り出します。これは Python 2.6+ における func.__defaults__ 、Python 2.5 における func.func_defaults と同じです。

six.get_function_globals(func)

func に関連付いた globals を取り出します。これは Python 2.6+ における func.__globals__ 、Python 2.5 における func.func_globals と同じです。

six.next(it)
six.advance_iterator(it)

イタレータ it の次のアイテムを取得します。末尾に到達すると StopIteration が送出されます。これは Python 2 での呼び出し it.next() と Python 3 における next(it) に対する置き換えです。

six.callable(obj)

obj が呼び出し可能であるかどうかを調べます。ただし。Python 3.2 に、callable が蘇りました。ですので、 six 版 callable が必要なのは、 Python 3.0 もしくは 3.1 をサポートする必要がある場合のみです。

six.iterkeys(dictionary, **kwargs)

dictionary の keys をめぐるイタレータを返します。これは Python 2 の dictionary.iterkeys() 、 Python 3 の dictionary.keys() に対する置き換えです。 kwargs は対応するメソッドに渡されます。

six.itervalues(dictionary, **kwargs)

dictionary の values をめぐるイタレータを返します。これは Python 2 の dictionary.itervalues() 、 Python 3 の dictionary.values() に対する置き換えです。 kwargs は対応するメソッドに渡されます。

six.iteritems(dictionary, **kwargs)

dictionary の items をめぐるイタレータを返します。これは Python 2 の dictionary.iteritems() 、 Python 3 の dictionary.items() に対する置き換えです。 kwargs は対応するメソッドに渡されます。

six.iterlists(dictionary, **kwargs)

Python 2 の dictionary.iterlists() 、 Python 3 の dictionary.lists() 呼び出しです。対応する Python に組み込みの mapping 型にはそのようなメソッドはありません; このメソッドは Werkzeug のもの のような、多値辞書に対して利用されることを意図しています。 kwargs は対応するメソッドに渡されます。

six.viewkeys(dictionary)

dictionary の keys についてのビューを返します。これは Python 2 の dict.viewkeys() 、 Python 3 の dict.keys() に対する置き換えです。

six.viewvalues(dictionary)

dictionary の values についてのビューを返します。これは Python 2 の dict.viewvalues() 、 Python 3 の dict.values() に対する置き換えです。

six.viewitems(dictionary)

dictionary の items についてのビューを返します。これは Python 2 の dict.viewitems() 、 Python 3 の dict.items() に対する置き換えです。

six.create_bound_method(func, obj)

func の、 obj に結合した結合メソッド(bound method)を返します。Python 2、3 のどちらでも、これは types.MethodType を返しますが、それでもこのラッパーが必要なのは、Python 2 での MethodType コンストラクタが*obj* の class を要求しているからです。

six.create_unbound_method(func, cls)

func の非結合メソッド (unbound method) を返します。Python 2 ではこれは types.MethodType です。Python 3 には 非結合メソッド (unbound method) は存在しないので、このラッパーはシンプルに func をそのまま返します。

class six.Iterator

移植性のあるイタレータを作るための class です。これは subclass 化して用い、subclass は __next__ を提供することで機能することを意図しています。Python 2 においては six の Iterator はたった一つのメソッド next を持っています。それは単純に __next__ に処理を委譲しています。 next__next__ へのエイリアスとして作る代替案はありますが、これはサブクラスが __next__ をオーバライドすることと相性が悪いです(のでそうしていません)。Python 3 では Iterator は空です。(実際、これは単に object へのエイリアスになっています。)

@six.wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, updated=functools.WRAPPER_UPDATES)

functools.wraps() デコレータに完全に同じですが、 version 3.2 以降の Python での functools.wraps() がそうするように それがデコレートするものに対して __wrapped__ 属性として wrapped をセットします。

Syntax compatibility

これら機能は、Python 2 と 3 で異なる文法を持つ操作を取り繕います。

six.exec_(code, globals=None, locals=None)

code を、 globalslocals スコープ内で実行します。code は文字列または code オブジェクトです。 globalslocals*が与えられない場合は、呼び出し元のスコープが使われます。 *globals のみが与えられた場合は、 それは locals としても使われます。

注釈

Python 3 の exec() はキーワード引数は受け取りません。従って、exec() にそれらを渡すことは避けなければなりません。

six.print_(*args, *, file=sys.stdout, end="\n", sep=" ", flush=False)

argsfile に印字します。各々の引数は sep によって区切られ、end が、最後の引数が印字されたのちに出力されます。flush が真の場合、全ての出力後に file.flush() が呼び出されます。

注釈

Python 2 の場合、これは Python 3 の関数 print() を、softspace サポートなしで模擬しています。なんのことかって? わからないなら多分それで問題ないよ :)

six.raise_from(exc_value, exc_value_from)

例外をコンテキストに基づき raise します。Python 3 ではこれは raise exc_value from exc_value_from と同じです。Python 2 では例外のチェインはサポートされていないので、 raise exc_value と同じです。

six.reraise(exc_type, exc_value, exc_traceback=None)

例外を、(きっと何か違うトレースバックとともに)再 raise します。単純なケースでは、 (except ブロック内で)現在アクティブな例外とともに reraise(*sys.exc_info()) を呼び出すことは、 最も最新のトレースバックとともに現在の例外を再 raise することになります。異なったトレースバックは、 exc_traceback として渡すことが出来ます。例外の再 raise は reraise() 内部で行われるため、Python はそれがどんなトレースバックであってもそれに reraise() の呼び出しフレームを追加することに注意してください。

six.with_metaclass(metaclass, *bases)

base class 群 bases と metaclass 群 metaclass に基づく新しい class を作ります。これは class 宣言において以下のように用いることを想定して設計されています:

from six import with_metaclass

class Meta(type):
    pass

class Base(object):
    pass

class MyClass(with_metaclass(Meta, Base)):
    pass

class にメタクラスをセットするもう一つの方法は、add_metaclass() デコレータを使うことです。

@six.add_metaclass(metaclass)

normally-constructed class を、 metaclass-constructed class に置き換えるためのclass デコレータです。このように使います:

@add_metaclass(Meta)
class MyClass(object):
    pass

これは

class MyClass(object, metaclass=Meta):
    pass

という Python 3 と同じコードを生成します。あるいは

class MyClass(object):
    __metaclass__ = MyMeta

という Python 2 と同じです。

class デコレータを使うには Python 2.6 以上が必要です。ただし、Python 2.5 でも以下のようにすれば同じ効果が得られます:

class MyClass(object):
    pass
MyClass = add_metaclass(Meta)(MyClass)

Binary and text data

Python 3 では、バイト列と文字列の区別が強制されるようになり、Python 2 におけるそれに比較して遥かに厳密になりました; これはすなわち、バイナリデータとテキストデータ間で自動的に強制変換することが出来なくなったということです。six はあらゆる Pythonバージョンにおいて文字列データを分類する、いくつかの機能を提供しています。

six.b(data)

bytes リテラルを模擬します。data は常に通常のリテラルであるべきです。Python 2 においては、b() は 8ビット文字で構成された文字列を返します。Python 3 では、 data は latin-1 エンコーディングにてバイト列にエンコードされます。

注釈

Python 2.6以降の全ての Python が b プレフィクスをサポートしているので、b() は、Python 2.5をサポートする必要がなければ、 b() は必要ありません。

six.u(text)

unicodeリテラルを模擬します。 text は常に通常のリテラルであるべきです。Python 2 では u() は unicode 型を返し、Python 3 では文字列型を返します。加えて、Python 2 においては、文字列は(結果を unicode escapes として利用可能とする) unicode-escape codec を使用してデコードされます。

注釈

In Python 3.3 において u プレフィクスが再導入されました。従って、Python 3 をサポートはするけれども Python 3.3 以降のみで良いならば、u() を使う必要はありません。

注釈

Python 2 の場合、u() は本当のところリテラルがどんなエンコーディングなのかを知りません。各バイトが直接コードポイントが同じ unicode に変換されます。従って、u() が安全なのは ASCII データの場合のみです。

six.unichr(c)

コードポイント c で表現される(Unicode)文字列を返します。これは Python 2 の unichr() 、 Python 3 の chr() と同じです。

six.int2byte(i)

i をバイトに変換します。irange(0, 256) の範囲内でなければなりません。これは Python 2 の chr() 、 Python 3 の bytes((i,)) と同じです。

six.byte2int(bs)

bs の先頭バイトを整数に変換します。これは Python 2 の ord(bs[0])、Python 3 の bs[0] と同じです。

six.indexbytes(buf, i)

buf の、インデクス i の位置のバイトを返します。これは Python 3 における、bytes オブジェクトのインデクシングと同じです。

six.iterbytes(buf)

buf 内 bytes 列に対しての、整数値としてのイタレータを返します。これは Python 3 における bytes オブジェクトのイタレータと同じです。

six.StringIO

テキストデータを収める、ファイルもどきオブジェクトです。Python 2 の StringIO.StringIO 、Python 3 の io.StringIO へのそれぞれ別名です。

six.BytesIO

バイナリデータを収める、ファイルもどきオブジェクトです。Python 2 の StringIO.StringIO、Python 3 の io.BytesIO へのそれぞれ別名です。

@six.python_2_unicode_compatible

__str__ メソッドを定義する class に対する class デコレータです。Python 3 の場合はこれは何もしません。Python 2 の場合は、 __str____unicode__ メソッドに別名化の上で新たに UTF-8 エンコードでエンコードされた __unicode__() の結果を返す __str__ メソッドを作成します。

unittest assertions

Six は、名前が変わってしまった unittest アサーションについての、互換性のための接ぎ木を提供しています。パラメータはその別名の元となるものと同じですが、テストを最初の引数として渡してください。例えば:

import six
import unittest

class TestAssertCountEqual(unittest.TestCase):
    def test(self):
        six.assertCountEqual(self, (1, 2), [2, 1])

これらの関数は Python 2.7 かそれ以上でのみ利用可能です。

six.assertCountEqual()

Python 3 の assertCountEqual() 、Python 2 の assertItemsEqual() への別名です。

six.assertRaisesRegex()

Python 3 の assertRaisesRegex() 、Python 2 の assertRaisesRegexp() への別名です。

six.assertRegex()

Python 3 の assertRegex() on Python 3 、 Python 2 の assertRegexpMatches() への別名です。

Renamed modules and attributes compatibility

Python 3 は標準ライブラリの再編成を行い、いくつかの機能は異なるモジュールに移動しました。 Six は six.moves なるフェイクを介すことで、それらに一貫したインターフェイスを提供しています。例えば、HTML を解析するモジュールをロードするために、このようにします:

from six.moves import html_parser

同じように、モジュールのリロードを行うための関数について、組み込み関数だったものが imp モジュールに移動しましたが、こうします:

from six.moves import reload_module

ほとんどのものについて、 six.moves は Python 3 名を採ります。新しい Python 3 名がパッケージである場合には、コンポーネントはアンダースコアで区切られた名前となります。例を挙げると、 html.parserhtml_parser となります。いくつかのモジュールが統合されたようないくつかのケースにおいては、Python 2 名が残されています。これにより、Python 2 で動作しているアプリケーションにとって適切なモジュールが理解しやすいです。例えば BaseHTTPServer は Python 3 では http.server ですが、これは BaseHTTPServer でエイリアスされています。

2つの実装が提供されていたいくつかのモジュールは Python 3 で統合されました。例えば cPickle は Python 3 にはもはや存在せず、 pickle にマージされています。これらのケースでは、Python 2 においては高速なものを、Python 3 ではマージされたものを返します。

urlliburllib2urlparse はPython 3 では urllib パッケージに統合されています。 six.moves.urllib は、これら機能へのバージョン非依存版となります; これは (Python 2 において) Python 3 の urllib パッケージを模擬します。

注釈

インポートするのにこのように:

from six.moves.cPickle import loads

これは動作します。six は sys.modules の中に特殊なプロキシオブジェクトを配置しているからです。これらプロキシは、属性のフェッチの際にモジュールを遅延ロードします。前提としたモジュールが Python インタプリタ内で利用不可能であれば、これは失敗するでしょう。例えば、 sys.modules["six.moves.winreg"].LoadKey は非 Windows プラットフォームでは失敗するでしょう。不幸なことに、いくつかのアプリケーションはあらゆるモジュールを sys.modules から取得しようと試みるのです。six は、いくつかのアプリケーションにとってのこうした問題に対し、存在しないことによってインポートできないモジュール名を避けることによって沈静化しています。このハックは、それでもいつでもうまくいくわけではありません。もしもあなたが遅延モジュールに関するこの問題に出くわしたならば、また、 six.moves から直接的にインポートするあらゆるものを使わないのであれば、six プロキシモジュールを取り除くことでこの問題に対処出来ます:

d = [name for name in sys.modules if name.startswith("six.moves.")]
for name in d:
    del sys.modules[name]

以下に対応しています:

Six名

Python 2 名

Python 3 名

builtins __builtin__ builtins
configparser ConfigParser configparser
copyreg copy_reg copyreg
cPickle cPickle pickle
cStringIO cStringIO.StringIO() io.StringIO
dbm_gnu gdbm dbm.gnu
_dummy_thread dummy_thread _dummy_thread
email_mime_multipart email.MIMEMultipart email.mime.multipart
email_mime_nonmultipart email.MIMENonMultipart email.mime.nonmultipart
email_mime_text email.MIMEText email.mime.text
email_mime_base email.MIMEBase email.mime.base
filter itertools.ifilter() filter()
filterfalse itertools.ifilterfalse() itertools.filterfalse()
getcwd os.getcwdu() os.getcwd()
getcwdb os.getcwd() os.getcwdb()
http_cookiejar cookielib http.cookiejar
http_cookies Cookie http.cookies
html_entities htmlentitydefs html.entities
html_parser HTMLParser html.parser
http_client httplib http.client
BaseHTTPServer BaseHTTPServer http.server
CGIHTTPServer CGIHTTPServer http.server
SimpleHTTPServer SimpleHTTPServer http.server
input raw_input() input()
intern intern() sys.intern()
map itertools.imap() map()
queue Queue queue
range xrange() range
reduce reduce() functools.reduce()
reload_module reload() imp.reload(), importlib.reload() on Python 3.4+
reprlib repr reprlib
shlex_quote pipes.quote shlex.quote
socketserver SocketServer socketserver
_thread thread _thread
tkinter Tkinter tkinter
tkinter_dialog Dialog tkinter.dialog
tkinter_filedialog FileDialog tkinter.FileDialog
tkinter_scrolledtext ScrolledText tkinter.scrolledtext
tkinter_simpledialog SimpleDialog tkinter.simpledialog
tkinter_ttk ttk tkinter.ttk
tkinter_tix Tix tkinter.tix
tkinter_constants Tkconstants tkinter.constants
tkinter_dnd Tkdnd tkinter.dnd
tkinter_colorchooser tkColorChooser tkinter.colorchooser
tkinter_commondialog tkCommonDialog tkinter.commondialog
tkinter_tkfiledialog tkFileDialog tkinter.filedialog
tkinter_font tkFont tkinter.font
tkinter_messagebox tkMessageBox tkinter.messagebox
tkinter_tksimpledialog tkSimpleDialog tkinter.simpledialog
urllib.parse

six.moves.urllib.parse 参照

urllib.parse
urllib.error

six.moves.urllib.error 参照

urllib.error
urllib.request

six.moves.urllib.request 参照

urllib.request
urllib.response

six.moves.urllib.response 参照

urllib.response
urllib.robotparser robotparser urllib.robotparser
urllib_robotparser robotparser urllib.robotparser
UserDict UserDict.UserDict collections.UserDict
UserList UserList.UserList collections.UserList
UserString UserString.UserString collections.UserString
winreg _winreg winreg
xmlrpc_client xmlrpclib xmlrpc.client
xmlrpc_server SimpleXMLRPCServer xmlrpc.server
xrange xrange() range
zip itertools.izip() zip()
zip_longest itertools.izip_longest() itertools.zip_longest()

urllib parse

Python の urllib.parse そのものであり、 Python 2 の以下です:

Python 2 の urlparse の以下に対応するもの:

そして Python 2 の urllib の以下に対応するもの:

urllib error

Python の urllib.error そのものであり、 Python 2 の以下です:

urllib:

そして urllib2:

urllib response

Python の urllib.response そのものであり、 Python 2 の以下です:

urllib:

  • urllib.addbase
  • urllib.addclosehook
  • urllib.addinfo
  • urllib.addinfourl

Advanced - Customizing renames

six.moves 名前空間に対して、さらなる名前を追加することが可能です。

six.add_move(item)

itemsix.moves マッピングに追加します。itemMovedAttribute もしくは MovedModule のインスタンスであるべきです。

six.remove_move(name)

six.moves マッピングから name 名を取り除きます。name は文字列であるべきです。

以下の class のインスタンスを add_move() に渡すことが出来ます。これらは公開メンバのいずれも含みません。

class six.MovedModule(name, old_mod, new_mod)

six.moves のための、 name で呼ばれ、Python 2 と 3 で異なるモジュールを参照するマッピングを作ります。 old_mod は Python 2 モジュールです。new_mod は Python 3 モジュールです。

class six.MovedAttribute(name, old_mod, new_mod, old_attr=None, new_attr=None)

six.moves のための、 name で呼ばれ、Python 2 と 3 で異なる属性を参照するマッピングを作ります。 old_mod は Python 2 モジュールです。new_mod は Python 3 モジュールです。 new_attr が省略された場合は、old_attr が使われます。ともに省略された場合は、 name が使われます。