What's New in Python 2.5

著者:

A.M. Kuchling

この記事では Python 2.5 の新機能を説明します。 Python 2.5 の最終リリースは 2006 年 8 月に予定されており、PEP 356 にリリース計画が記載されています。 Python 2.5 は 2006 年 9 月 19 日にリリースされました。

Python 2.5 には、言語とライブラリの興味深い改善が入り交じっています。 広い用途で役立つパッケージがいくつか追加されたので、Python のユーザーコミュニティにとってはライブラリの拡充の方が重要だと私は思います。 新しいモジュールには、XML 処理用の ElementTree (xml.etree.ElementTree)、SQLite データベースモジュール (sqlite3)、C 関数を呼び出すための ctypes モジュールなどがあります。

言語の変更の意義は、中程度のものです。いくつかの心地よい機能が入りましたが、そのほとんどの機能は毎日使うというものでもありません。条件式(conditional expressions)がついに言語に追加されました。ちょっと変わった文法です。 PEP 308: 条件式 (Conditional Expressions) のセクションを参照してください。新しい 'with' 文は後始末のコードを書くのを簡単にします(PEP 343: "with" ステートメント セクション)。ジェネレータに値を返すことが出来るようになりました(PEP 342: ジェネレータの新機能 セクション)。インポートが、絶対パス、相対パスのどちらかで可視に出来るようになりました(PEP 328: 絶対インポート、相対インポート セクション)。例外ハンドリングのいくつかの境界のケースで、より良いハンドリングを行えるようになりました(PEP 341: try/except/finally の一体化 セクション)。これらのどの改善も価値が高いですが、それらは言語機能を限定的に改善するものであって、いずれも Python のセマンティクスを広範に修正するものではありません。

言語とライブラリの追加と同様に、ほかの改善とバグフィックスもソースツリー全体に渡っています。SVN 変更ログを検索すると、Python 2.4 から 2.5 の間で適用されたパッチは 353、フィックスされたバグは 458 ありました(ともに少なく見積もってです)。

このドキュメントは新機能の完全な詳細を提供するのではなくて、変更について、役に立つ実例を使った簡易な概要を提供することを目的にしています。完全な詳細が知りたければ常に、 https://docs.python.org の Python 2.6 のドキュメントを参照すべきです。設計と実装の根拠を理解したい場合は、新機能に関する PEP を参照してください。可能な限り、 "What’s New in Python" は各変更の bug や patch に対してリンクしています。

このドキュメントについてのコメント、提案と誤りの報告は歓迎です。著者に電子メールを送るか、または Python バグトラッカーにバグをあげてください。

PEP 308: 条件式 (Conditional Expressions)

もう長いことずっと、人々は条件式を書くための手段を要望し続けてきました。それは Boolean 値が真か偽かによって値 A または B を返す式です。条件式により以下と同じ効果を持つ単一行代入式を書くことが出来ます:

if condition:
    x = true_value
else:
    x = false_value

構文についての退屈で終わりのない議論が python-dev と comp.lang.python の両方で続いてきました。投票では、大半は何らかの形で条件式を望んでいることを示していましたが、明らかな過半数によって支持される構文はありませんでした。候補には C の cond ? true_v : false_v や if cond then true_v else false_v を含む、ほか 16 のバリエーションがありました。

Guido van Rossum は結果として意外な構文を選択しました:

x = true_value if condition else false_value

評価はこれでも既存の Boolean 式のように遅延的であり、評価順は少々前後します。真ん中の condition はまさに最初に評価されるのであって、 true_value 式はその condition が真の場合にのみ評価されます。同じように false_value は condition が偽の場合にのみ評価されるのです。

この構文は奇妙で退行しているようにも思えます; どうして condition が 真ん中 にあって C の c ? x : y のように前にないのでしょう? この決定は、標準ライブラリ内のモジュールにその新構文を適用し、結果のコードをどう読むかを見ることでチェックされました。条件式が使われる多くの場合で、一つの値はどうやら「一般の場合」で一つの値は「例外的な場合」のようで、条件を満たさないことが稀な場合にのみ使われていました。条件の構文はこのパターンで少しばかり明快さを増します:

contents = ((doc + '\n') if doc else '')

私には上記ステートメントはこう読めます。「 contents は普通は doc+'\n' の値に代入される。ただし時々 doc が空になる。その特別な場合には空の値が代入されるのだ」。私は普通と普通でないのが明らかでない場合に頻繁に条件式を使うとは思いません。

言語が条件式に括弧を必要とすべきかどうかに関していくつか議論がありました。決定は Python 言語文法として括弧は 必要ない とされましたが、スタイルの問題としては私は常に括弧を付けるべきと思います。以下 2 つの例を考えてみてください:

# 最初の書き方 -- 括弧なし
level = 1 if logging else 0

# 2 つ目の書き方 -- 括弧あり
level = (1 if logging else 0)

最初の版の場合、私は読者の目はおそらくステートメントを「level = 1」「if logging」「else 0」にグループ化すると思います。そして condition は level への代入が行われるのかどうかを決めるのだ、と考えるであろうと。後者の版は読みやすいです、少なくとも私の意見では。代入はいつでも行われることも、選択が 2 つの値の間で起こることもはっきりしますから。

括弧を含めるもう一つの理由があります: 少し奇妙なリスト内包とラムダの組合せが、不完全な条件式になることがあります。 PEP 308 にいくつかの例があるので見てください。条件式の周りをいつでも括弧で囲むなら、このケースにぶち当たることもありません。

参考

PEP 308 - 条件式 (Conditional Expressions)

PEP 著 Guido van Rossum と Raymond D. Hettinger; 実装 Thomas Wouters.

PEP 309: 関数の部分適用

functools モジュールは、関数型スタイルのプログラミングのためのツールを含むことを意図したものです。

このモジュールの便利な道具の一つが partial() 関数です。 関数型のスタイルで書いたプログラムでは、既存の関数の引数の一部をあらかじめ指定した別の関数を作りたくなることがあります。 Python の関数 f(a, b, c) を考えてみてください。 f(1, b, c) と同じ働きをする新しい関数 g(b, c) を作ることができます。 これを「関数の部分適用」と呼びます。

partial() は (function, arg1, arg2, ... kwarg1=value1, kwarg2=value2) という引数を取ります。 返されるオブジェクトは呼び出し可能なので、そのまま呼び出せば、指定済みの引数を使って function を呼び出せます。

以下にあるのは、小さいけれども現実的な一つの例です:

import functools

def log (message, subsystem):
    "'message' の内容を指定したサブシステムへ書き込む。"
    print '%s: %s' % (subsystem, message)
    ...

server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')

PyGTK を使うプログラムから、別の例を示します。 ここでは、状況に応じたポップアップメニューを動的に作っています。 メニュー項目に渡すコールバックは、open_item() メソッドの最初の引数を指定した部分適用です。

...
class Application:
    def open_item(self, path):
       ...
    def init (self):
        open_func = functools.partial(self.open_item, item_path)
        popup_menu.append( ("Open", open_func, 1) )

functools モジュールには、適切に振る舞うデコレーターを書くのに役立つ update_wrapper(wrapper, wrapped) 関数もあります。 update_wrapper() は、名前、モジュール、docstring の属性をラッパー関数へコピーし、ラップした関数内のトレースバックを理解しやすくします。 例えば次のように書けます。

def my_decorator(f):
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    functools.update_wrapper(wrapper, f)
    return wrapper

wraps() は、自作のデコレーターの内部で使い、ラップした関数の情報をコピーするためのデコレーターです。 前の例は次のようにも書けます。

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    return wrapper

参考

PEP 309 - 関数の部分適用

PEP の提案と著: Peter Harris; 実装: Hye-Shik Chang と Nick Coghlan, また、適応物が Raymond Hettinger により。 (---訳注: この PEP のタイトルに違和感を憶える人は多いと思います。functools のテリトリが「関数型スタイルのサポート」にあるのに。部分引数サポートのためのパッチが最終的に関数型スタイルに行き着いた (正確には、「partial のような高階関数を置く場所として functools という場所を使いましょう、partial から始めましょう」というのが提案の趣旨)、という経緯がこのタイトルに反映しています。---)

PEP 314: Metadata for Python Software Packages v1.1

Distutils に簡単な依存関係のサポートが加わりました。 setup() 関数に requires、provides、obsoletes というキーワード引数が追加されました。 sdist コマンドでソース配布物を作ると、依存関係の情報が PKG-INFO に記録されます。

もう一つ追加されたキーワードパラメータ download_url は、パッケージのソースコードの URL をセットします。これによりパッケージインデクス内のエントリを探し出すことが出来、パッケージの依存性を決めることが出来、必要パッケージをダウンロード出来ます:

VERSION = '1.0'
setup(name='PyPackage',
      version=VERSION,
      requires=['numarray', 'zlib (>=1.1.4)'],
      obsoletes=['OldPackage']
      download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
                    % VERSION),
     )

Python Package Index (https://pypi.org) へのもう一つの新たな拡張は、パッケージについてのソースコードとバイナリアーカイブの保存についてです。新たな Distutils コマンド upload は、レポジトリへパッケージをアップロードします。

パッケージがアップロードされる前には、Distutils sdist コマンドを使って配布物をビルド可能でなければなりません。それさえ出来ていれば、 python setup.py upload がパッケージを PyPI アーカイブに追加してくれます。追加で、パッケージに GPG 署名出来ます。これには --sign オプションと --identity オプションを使います。

パッケージのアップロードは Martin von Löwis と Richard Jones により実装されました。

参考

PEP 314 - Metadata for Python Software Packages v1.1

PEP 提案と著 A.M. Kuchling、 Richard Jones、 Fred Drake; 実装 Richard Jones と Fred Drake.

PEP 328: 絶対インポート、相対インポート

PEP 328 のうち単純な部分は Python 2.4 で実装されました。 from ... import ... 文でモジュールからインポートする名前を括弧で囲めるようになり、多数の名前を簡単にインポートできるようになりました。

より複雑なほうは Python 2.5 で実装されました: モジュールのインポートにおいて、それが絶対インポートなのかパッケージ相対のインポートなのかを指定出来るようにする、というものです。将来のバージョンの Python では絶対インポートをデフォルトにする方向に向かう予定です。

いま、あなたは以下のようなパッケージディレクトリを持っているとします:

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

これは pkg.main と pkg.string というサブモジュールを含む、pkg というパッケージを定義します。

main.py モジュールのコードを考えてみましょう。 import string という文を実行すると何が起きるでしょうか。 Python 2.4 以前では、まず相対インポートのためにパッケージのディレクトリを調べ、pkg/string.py を見つけ、そのファイルの内容を pkg.string モジュールとしてインポートします。 そして pkg.main モジュールの名前空間で、名前 string をそのモジュールに束縛します。

欲しかったものが pkg.string なら、それで問題ありません。 しかし Python 標準の string モジュールが欲しかった場合はどうでしょうか。 pkg.string を無視して標準モジュールを探す簡潔な方法はなく、一般には sys.modules の内容を調べる必要があり、少しすっきりしませんでした。 Holger Krekel の py.std パッケージには import py; py.std.string.join() という、標準ライブラリからのインポートを行うより整った方法がありますが、このパッケージがすべての Python 環境にあるとは限りません。

相対インポートに依存するコードは、読む際にも分かりにくくなります。 string と pkg.string のどちらを使うつもりなのか、読み手が迷うかもしれないからです。 Python のユーザーは、パッケージのサブモジュールに標準ライブラリのモジュールと同じ名前を付けないように学びましたが、将来の Python で追加されるモジュールが自分のサブモジュールと同じ名前になることまでは防げません。

Python 2.5 では import の振る舞いを、 from __future__ import absolute_import ディレクティブを使うことによって絶対インポートに切り替えられます。この絶対インポートの振る舞いは将来バージョンの Python でデフォルトになります(おそらく Python 2.7 で)。(訳注: ご承知のとおり Python 2.7 でもこれはデフォルトとはなっていません。Python 3.x への移行のためにも 2.5 - 2.7 では from __future__ import absolute_import を使うべきです。) 絶対インポートをデフォルトにしてしまえば、 import string はいつでも標準ライブラリ版を見つけます。ユーザは可能な限り絶対インポートを使い始めるべきで、あなたのコードでは from pkg import string と書き始めることが望まれます。

相対インポートは、 from ... import 形式を使う際にモジュール名の前にピリオドを付ければまだ可能です:

# pkg.string から名前をインポート
from .string import name1, name2
# pkg.string をインポート
from . import string

これは現在のパッケージを基準に string モジュールをインポートするので、pkg.main 内では pkg.string から name1 と name2 をインポートします。 先頭のピリオドを増やすと、現在のパッケージの親を基準に相対インポートします。 例えば A.B.C モジュール内のコードでは次のように書けます。

from . import D                 # A.B.D をインポート
from .. import E                # A.E をインポート
from ..F import G               # A.F.G をインポート

このピリオドによる書き方は import modname 形式のインポート文では使えず、 from ... import 形式でのみ使えます。

参考

PEP 328 - マルチラインインポートと、絶対/相対インポート

PEP 著 Aahz; 実装 Thomas Wouters。

https://pylib.readthedocs.io/

py.std パッケージを含む、Holger Krekel の py ライブラリ。

PEP 338 - モジュールをスクリプトとして実行する

Python 2.4 で追加されたモジュールをスクリプトとして実行するための -m スイッチが、少し能力を高めました。Python インタプリタ内での C 実装に代わり、これの実現には新しいモジュール runpy を使うようになっています。

runpy モジュールは、より高度なインポートの仕組みを実装し、pychecker.checker のようなパッケージ内のモジュールを実行できるようにします。 zipimport モジュールなどの別のインポート方式にも対応しています。 そのため、.zip アーカイブのパスを sys.path に追加し、-m オプションでアーカイブ内のコードを実行できます。

参考

PEP 338 - モジュールをスクリプトとして実行する

PEP 著と実装 Nick Coghlan.

PEP 341: try/except/finally の一体化

Python 2.5 より前には、try 文には 2 つの形式がありました。 finally ブロックでコードが必ず実行されるようにするか、一つ以上の except ブロックで特定の例外を捕捉するかでした。 except ブロックと finally ブロックの両方を組み合わせることはできませんでした。 組み合わせた場合に正しいバイトコードを生成するのが複雑で、その文の意味をどうするべきかも明確ではなかったためです。

Guido van Rossum はいくらかの時間 Java での作業に時間を割きました。それは except ブロックと finally ブロックを組み合わせるのと等価なものをサポートしています。そしてこの作業が、このステートメントがどういう意味であるべきかを明らかにしたのです。Python 2.5 では、あなたは今ではこう書くことが出来ます:

try:
    block-1 ...
except Exception1:
    handler-1 ...
except Exception2:
    handler-2 ...
else:
    else-block
finally:
    final-block

まず block-1 のコードが実行されます。 例外が送出されると、except ブロックが順に調べられます。 例外のクラスが Exception1 なら handler-1、そうでなく Exception2 なら handler-2 というように実行されます。 例外が送出されなければ、else-block が実行されます。

以前に何が起こったのかに拠らず、コードブロック完了時やどれかの例外が処理されれば final-block が実行されます。例外ハンドラ内や else-block でエラーが起こったり、 新しく例外を投げる場合でさえ、 final-block 内のコードはそれでも実行されます。

参考

PEP 341 - try-except と try-finally を一体化する

PEP 著 Georg Brandl; 実装 Thomas Lee。

PEP 342: ジェネレータの新機能

Python 2.5 は、ジェネレータ に向けて 値を渡すための単純な手段を追加しました。Python 2.3 でジェネレータが導入された時点ではジェネレータが出来たのは出力だけでした。いったんジェネレータのコードが呼び出されてイテレータが作られたあとは、新しい情報をそのジェネレータ関数の再開位置に渡す手段はありませんでした。ヤクザな解決法としては、ジェネレータがグローバル変数を見るようにしたり、ミュータブルなオブジェクトを渡しておいて呼び出し元であとからそれを変更したり、といったものがありました。

基本的なジェネレータについて思い出してもらいましょう、単純な例はこんなです:

def counter (maximum):
    i = 0
    while i < maximum:
        yield i
        i += 1

counter(10) を呼び出すと、0 から 9 までの値を返すイテレータが得られます。 yield 文に到達すると、イテレータは指定された値を返し、ローカル変数を保持したまま関数の実行を一時停止します。 次にイテレータの next() メソッドを呼び出すと、yield 文の直後から実行を再開します。

Python 2.3 の yield は文で、値を返しませんでした。 2.5 の yield は式になり、変数への代入やほかの演算に使える値を返します。

val = (yield i)

戻り値に何かする際は、 yield 式の周りには括弧は付けておいたほうがいいと思います、この例でのように。括弧はべつに必要はないのですが、どんな場合に必要かを憶えるよりは、いつでも付けるのが簡単でしょう。

(PEP 342 がその規則を正確に説明していますが、それによると yield 式は、代入式で右辺のトップレベルにあるとき以外はいつも括弧を付ける必要があります。つまり val = yield i とは書けますが、 val = (yield i) + 12 のように演算子があるときは括弧を使わなくてはいけません。)

ジェネレータへ値を送るには、send(value) メソッドを呼び出します。 するとジェネレータの実行が再開され、yield 式が指定された value を返します。 通常の next() メソッドを呼び出した場合は、yield が None を返します。

以下は前のと同じ例ですが、内部カウンタの値の変更を許す修正をしました:

def counter (maximum):
    i = 0
    while i < maximum:
        val = (yield i)
        # 値を受け取ったらカウンターを変更
        if val is not None:
            i = val
        else:
            i += 1

そしてカウンタ変更の例がこちらです:

>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
  File "t.py", line 15, in ?
    print it.next()
StopIteration

yield は通常 None を返すので、その場合を必ず確認してください。 ジェネレータ関数の再開には send() メソッドしか使われないと確信できない限り、その値をそのまま式で使わないでください。

ジェネレータには send() に加えて、さらに 2 つの新しいメソッドがあります。

  • throw(type, value=None, traceback=None) はジェネレータ内で例外を投げるために使います; その例外はジェネレータの実行が停止したところの yield 式によって投げられます。

  • close() raises a new GeneratorExit exception inside the generator to terminate the iteration. On receiving this exception, the generator's code must either raise GeneratorExit or StopIteration. Catching the GeneratorExit exception and returning a value is illegal and will trigger a RuntimeError; if the function raises some other exception, that exception is propagated to the caller. close() will also be called by Python's garbage collector when the generator is garbage-collected.

    GeneratorExit が起こったときにクリーンアップ作業をする必要があるなら、 GeneratorExit を捕捉するのではなく try: ... finaly: するようお勧めします。

これらの変更の合わせ技で、ジェネレータは情報の一方的な生産者から、生産者かつ消費者という存在に変貌を遂げたのです。

ジェネレータは コルーチン という、より一般化された形式のサブルーチンにもなります。サブルーチンは一カ所 (関数の冒頭) から入って別の一カ所 (return 文) から出るだけですが、コルーチンはいろいろな場所 (yield 文) から入ったり出たり再開したりできるのです。わたしたちは Python でコルーチンを効果的に使うためのパターンを理解する必要があります。

close() メソッドの追加には、一見分かりにくい副次的な効果があります。 ジェネレータのガベージコレクション時に close() が呼ばれるので、破棄される前にコードが最後にもう一度実行される機会を得ます。 これによって、ジェネレータ内の try...finally 文の動作が保証され、finally 節には常に実行の機会が与えられます。 そのため、yield 文と try...finally スイートを混在させられないという構文上の制約が撤廃されました。 言語の些細な詳細に見えますが、ジェネレータと try...finally の併用は、PEP 343 で説明される with 文の実装に実際に必要です。 次の節で、この新しい文を見ていきます。

この変更には、さらに細かい影響もあります。 これまでジェネレータの gi_frame 属性は常にフレームオブジェクトでしたが、ジェネレータを使い切った後は gi_frame が None になることがあります。

参考

PEP 342 - 拡張されたジェネレータを用いたコルーチン

PEP は Guido van Rossum と Phillip J. Eby によって書かれ、Phillip J. Eby によって実装されました。コルーチンとしてのジェネレータの用法のいくつかの手が込んだ例が含まれています。

この機能の初期バージョンは Raymond Hettinger による PEP 288 と Samuele Pedroni による PEP 325 で提案されました。

https://en.wikipedia.org/wiki/Coroutine

コルーチンに関する WikiPedia エントリ。

https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html

Dan Sugalski による、Perl の視点からみたコルーチンの説明です。

PEP 343: "with" ステートメント

'with' ステートメントは、以前なら後片付けが実行されるのを確実にするために try...finally ブロックを使ったであろうようなコードを、より単純明快にします。このセクションでは、このステートメントの普通の使い方を説明します。続くセクションでは実装の詳細を調べ、このステートメントとともに使うためにオブジェクトをどうやって書けば良いかをお見せします。

'with' ステートメントは基本構造が以下となる新しい制御フロー構造です:

with expression [as variable]:
    with-block

式を評価した結果は、コンテキスト管理プロトコルに対応するオブジェクトである必要があります (つまり、__enter__() メソッドと __exit__() メソッドを備えている必要があります)。

with-block を実行する前にオブジェクトの __enter__() が呼ばれるため、そこで準備のコードを実行できます。 値を返すこともでき、variable が指定されていればその名前に束縛されます。 (variable に代入されるのは expression の結果では ない 点に注意してください。)

with-block の実行が終わると、ブロックが例外を送出した場合も含めて、オブジェクトの __exit__() メソッドが呼ばれるので、そこで後始末のコードを実行できます。

Python 2.5 でこのステートメントを有効にするには、以下のディレクティブをあなたのモジュールに追加する必要があります:

from __future__ import with_statement

Python 2.6 ではこれは常に有効になります。

いくつかの Python 標準オブジェクトが既にコンテキスト管理プロトコルをサポートしていて、 'with' とともに使えます。ファイルオブジェクトがその一例です:

with open('/etc/passwd', 'r') as f:
    for line in f:
        print line
        ... more processing code ...

このステートメントが実行し終わったあかつきには、 f のファイルオブジェクトは、たとえ for ループが道半ばにして例外と成り果てても、自動的にクローズされます。

注釈

この場合、__enter__() が self を返すので、f は open() が作ったオブジェクトそのものです。

threading モジュールのロック・条件変数でも 'with' ステートメントの恩恵にあずかれます:

lock = threading.Lock()
with lock:
    # コードのクリティカルセクション
    ...

ブロックが実行される前にロックが獲得されて、ブロックが完了するやいなや必ず解放されます。

decimal モジュールの新しい localcontext() 関数を使うと、演算に求める精度や丸め方法を保持する現在の十進数コンテキストを、簡単に保存・復元できます。

from decimal import Decimal, Context, localcontext

# デフォルトの精度である 28 桁で表示
v = Decimal('578')
print v.sqrt()

with localcontext(Context(prec=16)):
    # このブロック内のコードはすべて 16 桁の精度を使う。
    # ブロックを抜けると元のコンテキストに戻る。
    print v.sqrt()

コンテキストマネージャを書く

中身を紐解いてみれば、 'with' ステートメントはけっこう入り組んでいます。ほとんどの人にとっては、既存のオブジェクトを 'with' とともに使うだけのことでその詳細を知る必要は無いので、それで良いならこのセクションの残りの部分は読み飛ばして結構です。新しいオブジェクトの作者は基礎となる実装の詳細について知る必要があるので、このまま読み進めるべきです。

コンテキスト管理プロトコルの高度な説明はこんなです:

  • 式を評価した結果は、「コンテキストマネージャー」と呼ばれるオブジェクトである必要があります。 コンテキストマネージャーには __enter__() と __exit__() の両メソッドが必要です。

  • コンテキストマネージャーの __enter__() メソッドが呼ばれ、その戻り値が VAR に代入されます。 'as VAR' 節がなければ、値は単に捨てられます。

  • BLOCK 内のコードが実行されます。

  • BLOCK が例外を起こした場合、コンテキストマネージャの __exit__ メソッドが 3 つの引数とともに呼び出されます。これは例外の詳細です (type, value, traceback, これは sys.exc_info() が返す値と同じで、例外が起こらなければ None です)。そのメソッドの戻り値は例外を再送出するかどうかを制御します: 全ての偽の値ではその例外が再送出され、 True では揉み消します。例外を揉み消すなど滅多なことでは欲しいと思わないでしょう。もしそうしてしまったら、 'with' ステートメントを含んだコードの作者は何か間違ったことが起こったことに決して気付かないですから。

  • BLOCK が例外を送出しなかった場合も __exit__() メソッドは呼ばれますが、type、value、traceback はすべて None になります。

例を通じて考えましょう。枝葉末節を含んだ完璧なコードを提示しようとは思いませんが、データベースのためにトランザクションをサポートするのに必要となるメソッドの書き方についてスケッチしてみようと思います。

(データベース用語に不慣れな方へ:データベースへの変更のセットは、トランザクションという単位でグループ化されています。トランザクションは「コミット」される、その意味は、全ての変更がデータベースに書き込まれることです、もしくは「ロールバック」される、この場合全ての変更が捨てられてデータベースが変更されません、この 2 つのいずれかになりえます。詳しくはなにかデータベースの著述を読んで下さい。)

データベース接続を表現するオブジェクトがあると仮定しましょう。私たちの目標は、そのオブジェクトのユーザがこのように書けるようになることです:

db_connection = DatabaseConnection()
with db_connection as cursor:
    cursor.execute('insert into ...')
    cursor.execute('delete from ...')
    # ... その他の操作 ...

ブロック内のコードが問題なく実行されたらトランザクションをコミットし、例外が起きたらロールバックする必要があります。 ここでは DatabaseConnection の基本的なインターフェースを次のように想定します。

class DatabaseConnection:
    # データベースのインターフェース
    def cursor (self):
        "新しいトランザクションを開始し、カーソルオブジェクトを返す"
    def commit (self):
        "現在のトランザクションをコミットする"
    def rollback (self):
        "現在のトランザクションをロールバックする"

__enter__() メソッドは、新しいトランザクションを開始するだけなので簡単です。 この用途では、作成したカーソルオブジェクトを返すと便利なので、メソッドの戻り値にします。 利用者は with 文に as cursor を追加して、カーソルを変数名に束縛できます。

class DatabaseConnection:
    ...
    def __enter__ (self):
        # 新しいトランザクションを開始するコード
        cursor = self.cursor()
        return cursor

__exit__() メソッドは処理の大部分を担うため、最も複雑になります。 このメソッドは例外が発生したかどうかを確認する必要があります。 例外がなければトランザクションをコミットし、例外があればロールバックします。

下記のコード内では実行がメソッドの末尾まで落ちていって、なのでデフォルトの None 返却になります。 None は偽なので、例外は自動的に再送出されます。望むならもっと明示的に、コメントでマークした部分で return 文を書いてもよろしいです:

class DatabaseConnection:
    ...
    def __exit__ (self, type, value, tb):
        if tb is None:
            # 例外がないのでコミット
            self.commit()
        else:
            # 例外が発生したのでロールバック。
            self.rollback()
            # return False

contextlib モジュール

新しい contextlib モジュールは、 'with' ステートメントで使えるオブジェクトを書く際に便利ないくつかの関数とデコレータを提供しています。

このデコレーターは @contextmanager といい、新しいクラスを定義する代わりに、一つのジェネレータ関数を書けるようにします。 ジェネレータは値をちょうど一つだけ yield する必要があります。 yield までのコードは __enter__() メソッドとして実行され、yield した値がその戻り値になります。 with 文に as 節があれば、その変数に値が束縛されます。 yield より後のコードは __exit__() メソッド内で実行されます。 ブロック内で発生した例外は、yield 文から送出されます。

このデコレータを使って、前セクションの私たちのデータベースの例はこのように書けます:

from contextlib import contextmanager

@contextmanager
def db_transaction (connection):
    cursor = connection.cursor()
    try:
        yield cursor
    except:
        connection.rollback()
        raise
    else:
        connection.commit()

db = DatabaseConnection()
with db_transaction(db) as cursor:
    ...

contextlib モジュールには nested(mgr1, mgr2, ...) 関数もあり、この関数はたくさんのコンテキストマネージャを組み合わせることができて、入れ子の 'with' を書く必要性をなくしてくれます。この例では、単一の 'with' でデータベーストランザクション開始とスレッドのロック獲得の両方をやってのけています:

lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
    ...

最後になりますが、 closing(object) 関数は object をそのまま返して変数に束縛出来るようにし、かつブロックの終了で、与えた引数が持つ object.close を呼び出します:

import urllib, sys
from contextlib import closing

with closing(urllib.urlopen('http://www.yahoo.com')) as f:
    for line in f:
        sys.stdout.write(line)

参考

PEP 343 - "with" ステートメント

PEP は Guido van Rossum と Nick Coghlan によって書かれ、Mike Bland、 Guido van Rossum、Neal Norwitz により実装されました。この PEP は 'with' ステートメントによって生成されるコードを見せてくれるので、このステートメントがどうやって動作するのかを知るのに役立ちます。

contextlib モジュールについてのドキュメント。

PEP 352: 例外の新スタイルクラス化

例外クラスは、今では旧スタイルクラスだけではなく新スタイルクラスになれます。組み込みの Exception クラスと全ての標準組み込み例外 (NameError, ValueError, など) が今では新スタイルクラスです。

例外の継承階層が少し再編成されました。2.5 では継承関係はこのようになっています (---訳注: 2.6 ではさらに GeneratorExit が Exception ではなく BaseExceotion の直接の子になり、これは 3.x でも引き継がれています。---):

BaseException       # Python 2.5 で追加
|- KeyboardInterrupt
|- SystemExit
|- Exception
   |- (その他の現在の組み込み例外すべて)

この再編成が行われたのは、人々がしばしばプログラムのエラーを示す例外すべてを捕捉したがるからです。 KeyboardInterrupt と SystemExit はエラーではありませんが、普通は Control-C をユーザが叩いたか、コードが sys.exit() を呼び出したかのような明示的なアクションを表します。剥き出しの except: はまさに全ての例外を捕捉しますから、一般に、再送出のために KeyboardInterrupt と SystemExit はリストする必要があります。お決まりのパターンはこんなです:

try:
    ...
except (KeyboardInterrupt, SystemExit):
    raise
except:
    # エラーを記録...
    # プログラムの実行を続ける...

Python 2.5 では同じ結果を得るのにもう except Exception と書いても良いです。これは普通はエラーを示す例外全てを捕捉しつつも KeyboardInterrupt と SystemExit は置き去りにします。無論かつてまでのバージョン同様、剥き身の except: は全例外を捕捉します。

Python 3.0 での目標は、例外として raise される全てのクラスが BaseException からの、もしくは BaseException のある子孫であることを要求することであり、Python 2.x シリーズの将来のリリースにおいてはこの制約の強制を始めるかもしれません。ですからあなたの全ての例外は、今からすぐに Exception 派生にするのが肝要です。捕捉例外を特定しない except: は Python 3.0 から取り除かれるべきであることが提案されていますが、Guido van Rossum はこれをどうするかまだ決めていません。 (---訳注: 2.7 では raise は「新スタイルクラスであれば」 BaseException 派生であることを要求されますが、旧スタイルクラスであればなんでも許されてしまう点ではあまり変わっていません。これについての警告は -3 などで受けることが出来ます。Python 3.0 でようやく全ての例外が BaseException 派生であることが強制されるようになりました。 また、 except: は 3.4 でも残っています。---)

例外として文字列を raise "Error occurred" として raise することは Python 2.5 では非推奨であり警告を引き起こします。その目的は、あと少しのリリースで文字列例外を削除することです。 (---訳注: 2.6 以降の What's New では明示的に書かれてはいませんが、2.7 では警告ではなくエラーです。---)

参考

PEP 352 - 例外のためのスーパークラス

PEP 著: Brett Cannon と Guido van Rossum; 実装: Brett Cannon.

PEP 353: 添え字型に ssize_t を使う

Python の C API 全体にわたる変更として、int の代わりに新しい型定義 Py_ssize_t を使うようになり、64 ビット環境でインタープリタがより多くのデータを扱えるようになります。 32 ビット環境で Python が扱える容量には影響しません。

Python インタープリタの各所では、サイズや個数を格納するために C の int 型を使っていました。 例えば、リストやタプルの要素数は int に格納されていました。 ほとんどの 64 ビット環境の C コンパイラーでも int は 32 ビット型なので、リストは最大 2**31 - 1 = 2147483647 個の要素しか保持できませんでした。 (実際には 64 ビット C コンパイラーで使えるプログラミングモデルは複数あります。 議論は https://unix.org/version2/whatsnew/lp64_wp.html を参照してください。 ただし最も広く使われるモデルでは int は 32 ビットのままです。)

2147483647 に要素数が制限されることは 32 ビットプラットフォームではあまり重大でもありません。その長さ制限を喰らう前にメモリを使い果たすでしょうから。それぞれのリストアイテムは、ポインタのための領域 (4 バイト) をアイテムを表現する PyObject に余分に必要とします。2147483647*4 は既に 32 ビットのアドレス空間が含められるバイト数を超えています。(---訳注: 意味不明。何か誤解があるような…? 4 バイトは 2147483647 (符号付きとして 2^31 - 1) でしょう。4 を掛ける説明なんかここでまったくされていない。なぜ掛ける? それと要素のインデクシングとアイテムの必要領域は議論には無関係なのでは?---)

しかし、64 ビット環境ならそれだけのメモリにアクセスできます。 その大きさのリストでもポインターに必要な領域はわずか 16 GiB なので、Python のプログラマーがこれほど大きなリストを作ることも不合理ではありません。 そこで、Python インタープリタを int 以外の型を使うよう変更する必要があり、64 ビット環境では 64 ビットの型を使うことになりました。 この変更は 64 ビットマシンで非互換性を生じさせるため、その利用者がまだ比較的少ない今のうちに移行する価値があると判断されました。 (5 年後や 10 年後には 全員 が 64 ビットマシンを使っているかもしれず、その時の移行はもっと大変でしょう。)

この変更は C 拡張モジュールの著者に大変大きく影響します。Python 文字列とリストやタプルのようなコンテナ型は、そのサイズを表すのに Py_ssize_t を使うようになっています。 PyList_Size() のような関数は Py_ssize_t を返します。拡張モジュール内のコードでは、ですので、ある程度の変数の Py_ssize_t への変更が必要でしょう。

PyArg_ParseTuple() と Py_BuildValue() に、Py_ssize_t 用の新しい変換コード n が加わりました。 PyArg_ParseTuple() の s# と t# はデフォルトでは引き続き int を出力しますが、Python.h をインクルードする前に PY_SSIZE_T_CLEAN マクロを定義すると Py_ssize_t を返すようになります。

PEP 353 には、拡張の著者が読んで学ぶべき 64 ビットプラットフォームサポートについてのセクションがあります。

参考

PEP 353 - 添え字型に ssize_t を使う

PEP 著と実装 Martin von Löwis.

PEP 357: '__index__' メソッド

NumPy の開発者たちは、新しい特殊メソッド __index__() を追加する以外に解決できない問題に直面しました。 [start:stop:step] のようなスライス表記では、start、stop、step の値はすべて整数か長整数でなければなりません。 NumPy は 8、16、32、64 ビットの符号付き・符号なし整数に対応するさまざまな専用の整数型を定義していますが、それらをスライスのインデックスとして使えると示す方法がありませんでした。

スライスに既存の __int__() メソッドを使うだけでは済みません。 このメソッドは整数への型変換にも使われるためです。 スライスで __int__() を使うと、浮動小数点数も有効なスライスのインデックスになってしまい、明らかに望ましくありません。

代わりに、__index__() という新しい特殊メソッドが追加されました。 引数を取らず、スライスのインデックスとして使う整数を返します。 例えば次のようになります。

class C:
    def __index__ (self):
        return self.value

戻り値は Python 整数または長整数でなければなりません。インタプリタは戻り値が正しいかどうかをチェックし、要求に合わない場合に TypeError を送出します。

C 拡張でもこのプロトコルを実装できるよう、C レベルの PyNumberMethods 構造体に対応する nb_index スロットが追加されました。 拡張コードでは PyNumber_Index(obj) で __index__() 関数を呼び出し、その結果を取得できます。

参考

PEP 357 - スライシングのために任意のオブジェクトを使えるようにする

PEP 著と実装 Travis Oliphant.

その他の言語変更

以下が、Python 2.5 言語コアに加えられた全ての変更点です。

  • dict 型に、辞書にキーがない場合のデフォルト値をサブクラスで提供するためのフックが加わりました。 キーが見つからないと、辞書の __missing__(key) メソッドが呼ばれます。 このフックは collections モジュールの新しい defaultdict クラスの実装に使われています。 次の例は、存在しないキーに対して常にゼロを返す辞書を定義します。

    class zerodict (dict):
        def __missing__ (self, key):
            return 0
    
    d = zerodict({1:1, 2:2})
    print d[1], d[2]   # 1, 2 を表示
    print d[3], d[4]   # 0, 0 を表示
    
  • 8 ビット文字列、Unicode ともに、ありがちなユースケースを単純化する partition(sep) と rpartition(sep) が追加されました。

    文字列のスライスに使うために find(S) メソッドを使ってインデクスを得るのだけれども、やりたいのはそのセパレータ(S)の前後の部分文字列を得ることだ、といったことはしょっちゅう必要になります。partition(sep) はこのパターンのコードを、一撃、に圧縮してくれます。これはセパレータ前の部分文字列、セパレータ自身、セパレータ後の部分文字列の 3 要素タプルを返します。セパレータが含まれない場合は、返却値の最初の要素に文字列全体が、残り2つは空文字列で返ります。rpartition(sep) もほぼ同じことをしますがセパレータの検索をお尻から始めます。 r は逆順('reverse')を表します。

    いくつかの例です:

    >>> ('http://www.python.org').partition('://')
    ('http', '://', 'www.python.org')
    >>> ('file:/usr/share/doc/index.html').partition('://')
    ('file:/usr/share/doc/index.html', '', '')
    >>> (u'Subject: a quick question').partition(':')
    (u'Subject', u':', u' a quick question')
    >>> 'www.python.org'.rpartition('.')
    ('www.python', '.', 'org')
    >>> 'www.python.org'.rpartition(':')
    ('', '', 'www.python.org')
    

    (Implemented by Fredrik Lundh following a suggestion by Raymond Hettinger.)

  • 文字列型の startswith() と endswith() が、照合する文字列のタプルを受け付けるようになりました。

    def is_image_file (filename):
        return filename.endswith(('.gif', '.jpg', '.tiff'))
    

    (Implemented by Georg Brandl following a suggestion by Tom Lynn.)

  • 組み込み関数 min() と max() に、sort() の key 引数と同様のキーワード引数 key が加わりました。 この引数には、引数を一つ取り、リストの各値について呼ばれる関数を指定します。 min() と max() は、この関数の戻り値がそれぞれ最小、最大になる要素を返します。 例えば、リストで最も長い文字列を探すには次のようにします。

    L = ['medium', 'longest', 'short']
    # 'longest' を表示
    print max(L, key=len)
    # 辞書順では 'short' が最大なので 'short' を表示
    print max(L)
    

    (Contributed by Steven Bethard and Raymond Hettinger.)

  • 2 つの新たなビルトイン関数 any() と all() は、イテレータがいくつか真を含むかどうかを評価します。 any() はイテレータのいずれかが返す値が真と評価される場合に True を返し、そうでなければ False を返します。 all() はイテレータが返す値の評価が真のみの場合に True を返します。 (Suggested by Guido van Rossum, and implemented by Raymond Hettinger.)

  • クラスの __hash__() メソッドの戻り値に、通常の整数だけでなく長整数も使えるようになりました。 長整数が返された場合は、その値のハッシュが使われます。 これまではハッシュ値は通常の整数に限られていましたが、2.5 では組み込みの id() が常に非負の数を返すようになりました。 そして (推奨されませんが) __hash__() メソッドで id(self) を使う利用者が多いようです。

  • モジュールのデフォルトエンコーディングが ASCII になりました(訳注: Python 3 からはデフォルトは utf-8 (PEP 3120))。8 ビット文字を含んでいるのにエンコーディング宣言がないモジュールが構文エラーになるようになりました。Python 2.4 では構文エラーとはならず警告でした。モジュールのエンコーディングをする方法については PEP 263 を参照してください; 例えば、ソースコードの先頭付近にこのような行を追加することで出来ます:

    # -*- coding: latin1 -*-
    
  • Unicode 文字列とデフォルトの ASCII エンコーディングで Unicode に変換出来ない 8 ビット文字列との比較を試みると、新しい警告 UnicodeWarning が引き起こされるようになっています。比較結果は偽です:

    >>> chr(128) == unichr(128)   # chr(128) は Unicode に変換できない
    __main__:1: UnicodeWarning: Unicode equal comparison failed
      to convert both arguments to Unicode - interpreting them
      as being unequal
    False
    >>> chr(127) == unichr(127)   # chr(127) は変換できる
    True
    

    以前はこれは UnicodeDecodeError を起こしていましたので、2.5 でのこれは辞書のアクセス時に悩ましい問題をもたらしました。キーとして使われている unichr(128) や chr(128) を探そうとすると UnicodeDecodeError 例外が起こっていたでしょう。2.5 での、 辞書を実装している dictobject.c のほかの変更により、これは揉み消すのではなく、引き続き例外を起こします(訳注: 原文では this exception といっているので UnicodeDecodeError が起こるように読めるのですが、2.5 時点での振る舞いは確認出来ていませんが 2.7 では UnicodeWarning とともに KeyError が発生する、のようになるはずです。2.6 以降の What's New でのこれに関する言及はありませんが変更があったのかもしれません)。

    この種の比較で例外を起こすのは完全に正しいことではあるものの、その変更はコードを破壊するかもしれないので、必要に応じて警告に出来るよう導入されたのが UnicodeWarning です。

    (Implemented by Marc-André Lemburg.)

  • Python プログラマがよくしでかす間違いとして、パッケージディレクトリに __init__.py を入れ忘れる、というものがあります。この間違いのデバッグはややこしく、大抵 Python を -v スイッチ付きで起動して、パス検索全てをログ出力するハメになります。Python 2.5 ではパッケージディレクトリに __init__.py がないことが検出されると新たに ImportWarning 警告を出すようになりました。デフォルトではこの警告は黙って無視されます; これを出したければ、 -Wd スイッチをつけて Python を起動してください。(Implemented by Thomas Wouters.)

  • クラス定義において、基底クラスのリストを空リストに出来るようになっています(訳注: object を派生しないので結果として旧スタイルクラスになります)。例えば以下は今や合法です:

    class C():
        pass
    

    (Implemented by Brett Cannon.)

対話的なインタプリタの変更

対話的なインタプリタ内では、 quit と exit はずっと、立ち去ろうと(quit しようと)試みてそうタイプしてしまうユーザにとってある種有用な文字列になっていました:

>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'

Python 2.5 でも quit と exit はそれ自身そのような文字列を生成はしますが、同時に「呼び出す」ことが出来るオブジェクトになっています。初心者が思わず quit() や exit() してしまった場合、今では彼らが期待する通りにインタプリタが終了します。 (Implemented by Georg Brandl.)

Python 実行形式ファイルが標準的な長い形式の --help と --version を受け付けるようになりました。Windows の場合はヘルプメッセージを出力するのに /? オプションも受け付けます。(Implemented by Georg Brandl.)

最適化

この最適化のいくつかは、2006年5月21日から28日にかけてアイスランドのレイキャビクで開催されたイベント、NeedForSpeed sprintで開発されました。このスプリントはCPythonの実装のスピードアップに焦点を当て、EWT LLCが資金を提供し、CCP Gamesが現地でサポートしました。 このスプリントで追加された最適化については、以下のリストで特別にマークしています。

  • Python 2.4 が導入されたとき、組み込みの set と frozenset 型は Python の辞書型の上に構築されたものでした。 Python 2.5 では、内部データ構造がセットを実装するためにカスタマイズされ、その結果、セットのメモリ使用量は3分の1になり、多少高速化されました。(Raymond Hettinger による実装。)

  • 部分文字列の検索、文字列の分割、文字マップのエンコードとデコードなど、いくつかの Unicode 操作の速度が改善されました。 (部分文字列の検索と分割は、NeedForSpeed スプリントで Fredrik Lundh と Andrew Dalke が追加しました。部分文字列の検索と分割の改良は、NeedForSpeed sprintでFredrik LundhとAndrew Dalkeによって追加されました。文字マップは Walter Dörwald と Martin von Löwis によって改善されました。)

  • long(str, base) 関数は中間結果の計算回数が減り、長い数字列に対して高速になりました。 特に 800〜1000 桁ほどの文字列で効果が大きく、6 倍高速になっています。 (Alan McIntyre による貢献で、NeedForSpeed スプリントでコミットされました。)

  • for line in file によるファイルの反復と、ファイルオブジェクトの read()、readline()、readlines() メソッドの呼び出しを混在させられなくなりました。 反復は内部バッファを使いますが、read*() メソッドはそのバッファを使いません。 代わりにバッファより後のデータを返すため、データの順序が入れ替わったように見えていました。 反復とこれらのメソッドを混在させると、read*() メソッドが ValueError を送出するようになりました。 (Thomas Wouters による実装です。)

  • struct モジュールは構造体の書式文字列を内部表現にコンパイルしてキャッシュするようになり、20% 高速化しました。 (NeedForSpeed スプリントでの Bob Ippolito による貢献です。)

  • re モジュールは、システムの malloc() と free() の代わりに Python のアロケータ関数に切り替えることで、1~2%のスピードアップを達成しました。(NeedForSpeed sprintにてJack Diederichによるコントリビュート)

  • コードジェネレータの peephole オプティマイザは式の中で簡単な定数の折りたたみを実行するようになりました。 a = 2+3 のように書くと、コードジェネレータは算術演算を行い、 a = 5 に対応するコードを生成します。 (Raymond Hettinger による提案と実装。)

  • コードオブジェクトが直近に実行を終えたフレーム (「ゾンビフレーム」) を内部フィールドに保持し、次の呼び出しで再利用するようになったため、関数呼び出しが高速になりました。 (最初のパッチは Michael Hudson によるもので、Armin Rigo と Richard Jones が変更を加え、NeedForSpeed スプリントでコミットされました。) フレームオブジェクトも少し小さくなり、キャッシュの局所性やメモリ使用量が多少改善する可能性があります。 (Neal Norwitz による貢献です。)

  • Python の組み込み例外が新スタイルクラスになり、インスタンスの作成が大幅に高速化されました。 そのため、Python 2.5 の例外処理は 2.4 より約 30% 高速です。 (NeedForSpeed スプリントでの Richard Jones、Georg Brandl、Sean Reifschneider による貢献です。)

  • インポート時に調べたパスについて存在するかどうかをキャッシュするようになり、インタープリタ起動時の open() や stat() の呼び出し回数が減りました。 (Martin von Löwis と Georg Brandl による貢献です。)

新たなモジュール、改良されたモジュール、削除されたモジュール

標準ライブラリは Python 2.5 で数多くの拡張とバグフィックスを行っています。ここでは注目に値する変更をモジュール名の辞書順で列挙します。変更についてのもっと完全なリストが見たければソースツリーの Misc/NEWS を調べるか、全ての詳細について SVN ログに目を通してみてください。

  • audioop モジュールが a-LAW 符号化に対応し、u-LAW 符号化のコードも改善されました。 (Lars Immisch による貢献です。)

  • codecs モジュールに、インクリメンタルコーデックのサポートが加わりました。 codecs.lookup() 関数はタプルではなく CodecInfo インスタンスを返すようになりました。 CodecInfo インスタンスは後方互換性のために 4 要素のタプルのように振る舞いますが、encode、decode、incrementalencoder、incrementaldecoder、streamwriter、streamreader という属性も持ちます。 インクリメンタルコーデックは入力や出力を複数の断片に分けて処理でき、出力結果は入力全体を通常のコーデックに渡した場合と同じになります。 詳細は codecs モジュールの文書を参照してください。 (Walter Dörwald による設計と実装です。)

  • collections モジュールに、標準の dict 型を継承する新しい型 defaultdict が加わりました。 ほぼ辞書と同じように振る舞いますが、キーがなければデフォルト値を作り、要求されたキーの値として辞書に自動的に追加します。

    defaultdict のコンストラクターの最初の引数は、要求されたキーが見つからないたびに呼ばれるファクトリー関数です。 この関数は引数を取らないので、list() や int() などの組み込み型のコンストラクターを使えます。 例えば、単語を頭文字ごとに索引にまとめるには次のようにします。

    words = """Nel mezzo del cammin di nostra vita
    mi ritrovai per una selva oscura
    che la diritta via era smarrita""".lower().split()
    
    index = defaultdict(list)
    
    for w in words:
        init_letter = w[0]
        index[init_letter].append(w)
    

    index を出力するとこんな具合です:

    defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
            'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
            'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
            'p': ['per'], 's': ['selva', 'smarrita'],
            'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
    

    (Contributed by Guido van Rossum.)

  • collections モジュールの両端キュー型 deque に、キューに最初に現れる value を削除する remove(value) メソッドが加わりました。 値が見つからなければ ValueError を送出します。 (Raymond Hettinger による貢献です。)

  • 新規モジュール: contextlib モジュールには 'with' ステートメントで使えるヘルパ関数が含まれています。詳細は contextlib モジュール をみてください。

  • New module: The cProfile module is a C implementation of the existing profile module that has much lower overhead. The module's interface is the same as profile: you run cProfile.run('main()') to profile a function, can save profile data to a file, etc. It's not yet known if the Hotshot profiler, which is also written in C but doesn't match the profile module's interface, will continue to be maintained in future versions of Python. (Contributed by Armin Rigo.)

    また、プロファイラーの測定データを解析する pstats モジュールでは、Stats のコンストラクターに stream 引数を渡すと、任意のファイルオブジェクトへ出力できるようになりました。 (Skip Montanaro による貢献です。)

  • カンマ区切り形式のファイルを解析する csv モジュールに、いくつかの機能追加と多数のバグ修正が行われました。 csv.field_size_limit(new_limit) 関数でフィールドの最大サイズをバイト単位で設定でき、new_limit 引数を省略すると現在の上限を返します。 reader クラスに、入力元から読み取った物理的な行数を数える line_num 属性が加わりました。 レコードは複数の物理行にまたがる場合があるため、line_num は読み取ったレコード数とは異なります。

    CSV パーサは引用符内のマルチラインをより厳密に扱うようになっています。以前は、引用符で囲まれたフィールドが改行文字(newline)で終了することなく終端すると、改行文字が返却フィールドに追加されていました。この振る舞いはフィールドに復帰文字(carriage return)を含んだファイルを読み込む際に問題だったため、改行文字を挿入することなくフィールドを返すように変更されました。このことにより、フィールド内に埋め込まれた改行文字が重要な場合、入力は改行文字が保存される方法で行分割されるはずです。(---訳注: リファレンスも含めこの説明の表現がわかりにくいです。行指向で読み込む場合改行コードのモード(NL, CR NL, CR)依存で「物理行が終了した」とみなされるわけですが、このモード依存(CR 時)の振る舞いがなくなった、ということです。---)

    (Contributed by Skip Montanaro and Andrew McNamara.)

  • datetime モジュールの datetime クラスに、日付の文字列を解析する strptime(string, format) メソッドが加わりました。 Josh Spoerri による貢献で、time.strptime() や time.strftime() と同じ書式文字を使います。

    import datetime as dt
    
    ts = dt.datetime.strptime('10:13:15 2006-03-07',
                              '%H:%M:%S %Y-%m-%d')
    
  • difflib モジュールの difflib.SequenceMatcher.get_matching_blocks() メソッドは、一致する部分列を表す最小のブロックのリストを返すことを保証するようになりました。 これまでは、一致する要素のブロックを 2 つのリスト要素に分けてしまう場合がありました。 (Tim Peters による改善です。)

  • doctest モジュールに、実行されるべきものから例を守る SKIP オプションが追加されています。これは、読者のための使用例として意図しているけれども実際のテストケースとして意図していないようなコードスニペットのために用意されました。

    An encoding parameter was added to the testfile() function and the DocFileSuite class to specify the file's encoding. This makes it easier to use non-ASCII characters in tests contained within a docstring. (Contributed by Bjorn Tillenius.)

  • email パッケージがバージョン 4.0 にアップデートされました (Contributed by Barry Warsaw.)

  • fileinput モジュールがより柔軟になりました。 Unicode のファイル名に対応し、input() 関数にデフォルト値 "r" の mode 引数が追加されたことで、バイナリモードや universal newlines モードでファイルを開けます。 もう一つの新しい引数 openhook を使うと、入力ファイルを開くのに open() 以外の関数を使えます。 複数のファイルを反復している間、FileInput オブジェクトの新しい fileno() メソッドで、現在開いているファイルのファイル記述子を取得できます。 (Georg Brandl による貢献です。)

  • In the gc module, the new get_count() function returns a 3-tuple containing the current collection counts for the three GC generations. This is accounting information for the garbage collector; when these counts reach a specified threshold, a garbage collection sweep will be made. The existing gc.collect() function now takes an optional generation argument of 0, 1, or 2 to specify which generation to collect. (Contributed by Barry Warsaw.)

  • heapq モジュールの nsmallest() と nlargest() に、min()、max() 関数や sort() メソッドと同様のキーワード引数 key が加わりました。 例えば次のようになります。

    >>> import heapq
    >>> L = ["short", 'medium', 'longest', 'longer still']
    >>> heapq.nsmallest(2, L)  # 辞書順で最小の 2 要素を返す
    ['longer still', 'longest']
    >>> heapq.nsmallest(2, L, key=len)   # 最も短い 2 要素を返す
    ['short', 'medium']
    

    (Contributed by Raymond Hettinger.)

  • itertools.islice() 関数が start と step として None を受け付けるようになっています。これは slice オブジェクトとの互換性を高めるもので、つまり以下のように書くことが出来ます:

    s = slice(5)     # スライスオブジェクトを作る
    itertools.islice(iterable, s.start, s.stop, s.step)
    

    (Contributed by Raymond Hettinger.)

  • locale モジュールの format() 関数が変更され、新しい関数 format_string() と currency() が加わりました。

    format() 関数の val パラメータは以前は一つ以上の %文字指定子が現れる文字列が許されていました; 今はこのパラメータは正確に一つの %文字指定子を含む、周りに囲むテキストのない文字列でなければなりません。省略可能な monetary パラメータも追加されています。これが True の場合、通貨の書式化の 3 桁ごとに区切るセパレータに、ロケールのルールを使います。

    複数の %char 指定子を含む文字列を書式化するには、新しい format_string() 関数を使ってください。 format() と同様に動作しますが、%char 指定子と任意のテキストを混在させられます。

    現在のロケールの設定に従って数値を書式化する、新しい currency() 関数も加わりました。

    (Contributed by Georg Brandl.)

  • mailbox モジュールが大幅に書き直され、メールボックスの読み取りだけでなく変更もできるようになりました。 読み取りには mbox、MH、Maildir などの新しいクラスを使います。 これらには、メッセージを追加する add(message)、削除する remove(key)、メールボックスをロック・解除する lock() と unlock() があります。 次の例は maildir 形式のメールボックスを mbox 形式へ変換します。

    import mailbox
    
    # 'factory=None' は、個々のメッセージを表すクラスとして
    # email.Message.Message を使う。
    src = mailbox.Maildir('maildir', factory=None)
    dest = mailbox.mbox('/tmp/mbox')
    
    for msg in src:
        dest.add(msg)
    

    (Contributed by Gregory K. Johnson. Funding was provided by Google's 2005 Summer of Code.)

  • 新モジュール msilib で、Microsoft Installer の .msi ファイルや CAB ファイルを作れるようになりました。 .msi データベースの読み取り機能も一部含まれます。 (Martin von Löwis による貢献です。)

  • nis モジュールで、nis.match() や nis.maps() 関数に domain 引数を指定すると、システムのデフォルト以外のドメインにもアクセスできるようになりました。 (Ben Bell による貢献です。)

  • operator モジュールの itemgetter() と attrgetter() が、複数のフィールドに対応しました。 operator.attrgetter('a', 'b') のように呼び出すと、a 属性と b 属性を取得する関数が返ります。 この機能と sort() の key 引数を組み合わせれば、複数のフィールドを基準にリストを簡単にソートできます。 (Raymond Hettinger による貢献です。)

  • optparse モジュールが Optik ライブラリのバージョン 1.5.1 に更新されました。 OptionParser クラスに、ヘルプの後に表示する文字列を保持する epilog 属性と、オブジェクトが作る循環参照を解消する destroy() メソッドが加わりました。 (Greg Ward による貢献です。)

  • The os module underwent several changes. The stat_float_times variable now defaults to true, meaning that os.stat() will now return time values as floats. (This doesn't necessarily mean that os.stat() will return times that are precise to fractions of a second; not all systems support such precision.)

    os.SEEK_SET、os.SEEK_CUR、os.SEEK_END という定数が追加されました。 これらは os.lseek() 関数の引数に使います。 ロック用には os.O_SHLOCK と os.O_EXLOCK の 2 つの定数が加わりました。

    新しい関数 wait3() と wait4() が加わりました。 子プロセスの終了を待ち、プロセス ID と終了ステータスのタプルを返す waitpid() に似ていますが、wait3() と wait4() は追加の情報も返します。 wait3() は入力としてプロセス ID を取らず、任意の子プロセスの終了を待ち、process-id、exit-status、resource-usage の 3 要素のタプルを返します。 最後の要素は resource.getrusage() 関数が返す形式です。 wait4(pid) はプロセス ID を受け取ります。 (Chad J. Schroeder による貢献です。)

    FreeBSD では os.stat() がナノ秒の分解能で時刻を返すようになり、戻り値のオブジェクトに st_gen と st_birthtime が加わりました。 プラットフォームが対応していれば st_flags 属性も利用できます。 (Antti Louko と Diego Pettenò による貢献です。)

  • pdb モジュールで提供される Python デバッガが、ブレイクポイントに到達して実行が停止する際に実行するコマンドのリストを記憶するようになりました。ブレイクポイント #1 を作ったら、 commands 1 を入力し、実行するコマンド群を入力し、 end でリストを終えます。コマンドリストには continue や next のような実行再開コマンドを含めることが出来ます。 (Contributed by Grégoire Dooms.)

  • pickle と cPickle モジュールは、__reduce__() メソッドの戻り値として None を受け付けなくなりました。 代わりに引数のタプルを返す必要があります。 None を返す機能は Python 2.4 で非推奨となっており、これで削除が完了します。

  • パッケージの検索などのユーティリティ関数を含む pkgutil モジュールが、PEP 302 のインポートフックに対応し、ZIP 形式のアーカイブ内のパッケージでも動作するようになりました。 (Phillip J. Eby による貢献です。)

  • Marc-André Lemburg による pybench ベンチマークスイートが Tools/pybench ディレクトリに含まれるようになりました。pybench スイートは、広く使われている pystone.py プログラムの改善版で、インタプリタの速度についてのより詳しい計測を行います。 pystone.py のように多くの異なる演算を実行したり単独の数字に縮退する代わりに、これは関数コール、タプルのスライス、メソッドの検索、数値演算のような特定の演算を計測します。 (---訳注: Tools についての言及すべてに共通することですが、原則として Tools は「全て」を入手する手段はソースコード配布を利用することだけです。インストールされるものはプラットフォーム依存や linux であればディストリビュータによっても変わります。顕著なのは Windows で、Tools 配下のものはごく限られたものだけがインストールされます。pybench もソースコード配布物にのみ含まれ、Windows 公式インストーラではインストールされません。なお、 pystone.py は Lib/test 内にあります。---)

  • pyexpat モジュールが Expat パーサーのバージョン 2.0 を使うようになりました。 (Trent Mick による貢献です。)

  • queue モジュールの Queue クラスに 2 つのメソッドが加わりました。 join() は、キュー内のすべての要素が取り出され、その処理がすべて終わるまでブロックします。 ワーカースレッドは、もう一方の新しいメソッド task_done() を呼び出して、要素の処理が終わったことを知らせます。 (Raymond Hettinger による貢献です。)

  • Python 2.0 から非推奨だった古い regex と regsub モジュールが、ついに削除されました。 statcache、tzparse、whrandom も削除されました。

  • dircmp や ni といった非常に古いモジュールを含む lib-old ディレクトリも削除されました。 lib-old はデフォルトの sys.path に含まれていなかったので、プログラムで明示的に sys.path へ追加していなければ、この削除による影響はないはずです。

  • rlcompleter モジュールが readline モジュールのインポートに依存しないようになりました。これにより非 Unix プラットフォームで動作するようになりました。 (Patch from Robert Kiendl.)

  • The SimpleXMLRPCServer and DocXMLRPCServer classes now have a rpc_paths attribute that constrains XML-RPC operations to a limited set of URL paths; the default is to allow only '/' and '/RPC2'. Setting rpc_paths to None or an empty tuple disables this path checking.

  • Philippe Biondi のパッチにより、socket モジュールが Linux の AF_NETLINK ソケットをサポートするようになりました。 Netlink ソケットはユーザー空間のプロセスとカーネルコードが通信するための Linux 固有の仕組みです。 紹介記事は https://www.linuxjournal.com/article/7356 にあります。 Python のコードでは netlink アドレスを 2 つの整数のタプル (pid, group_mask) で表します。

    ソケットオブジェクトの 2 つの新たなメソッド、 recv_into(buffer), recvfrom_into(buffer) は、受信データを、文字列データとして返す代わりにバッファプロトコルをサポートするオブジェクトに書き込みます。このことにより、受信データを直接 array やメモリマップドファイルに置けます。

    Socket objects also gained getfamily(), gettype(), and getproto() accessor methods to retrieve the family, type, and protocol values for the socket.

  • 新モジュール spwd は、シャドウパスワードに対応するシステムで、そのデータベースにアクセスする関数を提供します。

  • struct は、書式文字列を pack() と unpack() メソッドを備える Struct オブジェクトにコンパイルするようになり、高速化しました。 これは re モジュールでコンパイル済み正規表現オブジェクトを作れることに似ています。 従来どおりモジュールレベルの pack() と unpack() も使え、内部で Struct オブジェクトを作成してキャッシュします。 あるいは Struct インスタンスを直接使うこともできます。

    s = struct.Struct('ih3s')
    
    data = s.pack(1972, 187, 'abc')
    year, number, name = s.unpack(data)
    

    pack_into(buffer, offset, v1, v2, ...) と unpack_from(buffer, offset) メソッドで、バッファオブジェクトへ直接パックしたり、そこからアンパックしたりできます。 これにより、配列やメモリマップファイルへデータを直接格納できます。

    (Struct オブジェクトは、NeedForSpeed スプリントで Bob Ippolito が実装しました。 バッファオブジェクトのサポートは、同じスプリントで Martin Blais が追加しました。)

  • Python デベロッパは 2.5 開発プロセスの間で CVS から Subversion に移行しました。ビルドバージョンについての正確な情報は sys.subversion により取得可能で、これは 3 要素タプル (interpreter-name, branch-name, revision-range) です。例えば執筆時点では 2.5 で ('CPython', 'trunk', '45313:45315') を返します。 (---訳注: Python 3.2 から 3.3 にかけて、開発が Mercurial に移行していて、これは 2.7 メンテナンスリリースの間にあたります。今(3.6 dev 時点)では全て Mercurial に移行しており、 sys.subversion は今では意味のある値は返しません。3.3 からは既に sys.subversion は削除されています。---)

    この情報は C 拡張から Py_GetBuildInfo() 関数を使っても得ることが出来ます。これはビルド情報についての文字列を返し、例えば "trunk:45355:45356M, Apr 13 2006, 07:42:19" のような値です。 (Contributed by Barry Warsaw.)

  • もう一つの新規関数 sys._current_frames() は、実行スレッドについての現在スタックフレームを、各スレッドの識別子がキーの辞書として返します。辞書の値は、関数が呼ばれた時点のそのスレッドで現在アクティブになっているスタックフレームの一番上です。(Contributed by Tim Peters.)

  • tarfile モジュールの TarFile クラスに、アーカイブの全メンバーを現在の作業ディレクトリへ展開する extractall() メソッドが加わりました。 展開先に別のディレクトリを指定したり、アーカイブのメンバーの一部だけを展開したりすることもできます。

    ストリームモードで開く tarfile に使われる圧縮を、モード 'r|*' を使って自動で検出出来るようになっています。 (Contributed by Lars Gustäbel.)

  • threading モジュールで、新しいスレッドを作る際に使われるスタックサイズを設定出来るようになりました。 stack_size([*size*]) 関数は現在構成されているスタックサイズを返し、省略可能引数 size パラメータを与えると新しい値を設定します。全てのプラットフォームがスタックサイズ変更をサポートしているわけではなく、Windows、POSIX スレッド、OS/2 で可能です。 (Contributed by Andrew MacIntyre.)

  • unicodedata モジュールが Unicode 文字データベースのバージョン 4.1.0 を使うよう更新されました。 バージョン 3.2.0 を必要とする仕様もあるため、そちらも unicodedata.ucd_3_2_0 として引き続き利用できます。

  • 新モジュール uuid は、RFC 4122 に従う汎用一意識別子 (UUID) を生成します。 この RFC では、文字列やシステムの情報をもとにするもの、完全にランダムなものなど、複数の UUID バージョンが定義されています。 モジュールには UUID クラスと、各バージョンの UUID を生成する uuid1()、uuid3()、uuid4()、uuid5() 関数があります。 (バージョン 2 の UUID は RFC 4122 では規定されず、このモジュールでもサポートされていません。)

    >>> import uuid
    >>> # ホスト ID と現在の時刻をもとに UUID を作る
    >>> uuid.uuid1()
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
    >>> # 名前空間 UUID と名前の MD5 ハッシュから UUID を作る
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
    >>> # ランダムな UUID を作る
    >>> uuid.uuid4()
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
    >>> # 名前空間 UUID と名前の SHA-1 ハッシュから UUID を作る
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    

    (Contributed by Ka-Ping Yee.)

  • weakref モジュールの WeakKeyDictionary と WeakValueDictionary に、辞書内の弱参照を反復する新しいメソッドが加わりました。 WeakKeyDictionary には iterkeyrefs() と keyrefs()、WeakValueDictionary には itervaluerefs() と valuerefs() が追加されました。 (Fred L. Drake, Jr. による貢献です。)

  • webbrowser モジュールに多数の改善が加わりました。 URL を引数に渡して python -m webbrowser というスクリプトとして使えるようになり、動作を制御するオプションもあります (-n は新しいブラウザーウィンドウ、-t は新しいタブ)。 これを支えるモジュールレベルの関数 open_new() と open_new_tab() も加わりました。 モジュールの open() 関数には、可能なら開いたウィンドウを前面に出すかどうかを指定する autoraise パラメーターが加わりました。 Firefox、Opera、Konqueror、elinks など、対応ブラウザーも増えました。 (Oleg Broytmann と Georg Brandl による貢献です。)

  • xmlrpclib モジュールで、XML-RPC の日付型に対して datetime オブジェクトを返せるようになりました。 loads() 関数や Unmarshaller クラスに use_datetime=True を指定すると有効になります。 (Skip Montanaro による貢献です。)

  • zipfile モジュールが ZIP64 バージョンのフォーマットをサポートしました。これで 4GiB を超える zip 書庫を作れ、4GiB を超えるファイルを書庫に含めることが出来ます。 (Contributed by Ronald Oussoren.)

  • zlib モジュールの Compress と Decompress オブジェクトに、内部状態をコピーして新しい Compress または Decompress オブジェクトを返す copy() メソッドが加わりました。 (Chris AtLee による貢献です。)

ctypes パッケージ

Thomas Heller が書いた ctypes パッケージが標準ライブラリに加わりました。 ctypes を使うと、共有ライブラリや DLL 内の任意の関数を呼び出せます。 長年の利用者なら、共有ライブラリの読み込みやその関数の呼び出しを行う dl モジュールを覚えているかもしれません。 ctypes パッケージは、はるかに高機能です。

共有ライブラリや DLL を読み込むには、その名前やパスを指定して CDLL クラスのインスタンスを作成します。 その後は CDLL オブジェクトの属性としてアクセスすることで、任意の関数を呼び出せます。

import ctypes

libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")

各種 C の型に対応する型コンストラクターが用意されています。 c_int()、c_float()、c_double()、c_char_p() (char* に相当) などです。 Python の型と異なり、C 版はすべてミュータブルで、value 属性に代入すると保持する値を変更できます。 Python の整数や文字列は対応する C の型へ自動的に変換されますが、それ以外の型では正しい型コンストラクターを呼び出す必要があります。 (これは 必須 です。間違えると、セグメンテーション違反でインタープリタがクラッシュすることがよくあります。)

C 関数がメモリ領域を書き換える場合は、Python の文字列に c_char_p() を使わないでください。 Python の文字列はイミュータブルであるはずなので、この規則を破ると不可解なバグにつながります。 変更できるメモリ領域が必要なら、create_string_buffer() を使ってください。

s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)

C 関数は整数を返すと想定されますが、関数オブジェクトの restype 属性を設定すれば変更できます。

>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828

ctypes は、Python の C API のラッパーも ctypes.pythonapi オブジェクトとして提供します。 インタープリタのコードを呼び出すにはロックを保持する必要があるため、このオブジェクトは関数を呼び出す前にグローバルインタープリタロックを解放 しません。 PyObject* ポインターを作る型コンストラクター py_object があります。 簡単な使用例を示します。

import ctypes

d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
          ctypes.py_object("abc"),  ctypes.py_object(1))
# d is now {'abc', 1}.

py_object() を忘れずに使ってください。 省略するとセグメンテーション違反になります。

ctypes が周辺ライブラリとして登場してしばらく経ちますが、ctypes が存在していることに依存できないとなれば人々はまだハードコードされた拡張モジュールを書いて配布します。 ctypes が Python 中核に含められた今、おそらく開発者たちは、拡張モジュールの代わりに ctypes を介してアクセスするライブラリの上に Python ラッパーを書き始めるでしょう,

参考

https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/

標準ライブラリに入る前の ctypes の Web ページ。チュートリアル、リファレンス、FAQ があります。

ctypes モジュールについてのドキュメント。

ElementTree パッケージ

Fredrik Lundh の XML 処理用ライブラリ ElementTree の一部が、xml.etree として標準ライブラリに加わりました。 ElementTree 1.2.6 の ElementTree、ElementPath、ElementInclude モジュールが利用できます。 高速化用の cElementTree モジュールも含まれます。

この節の残りでは、ElementTree の使い方を簡単に紹介します。 詳しい文書は https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm にあります。

ElementTree represents an XML document as a tree of element nodes. The text content of the document is stored as the text and tail attributes of (This is one of the major differences between ElementTree and the Document Object Model; in the DOM there are many different types of node, including TextNode.)

最もよく使う解析関数は parse() です。 ファイル名を表す文字列またはファイル風オブジェクトを受け取り、ElementTree インスタンスを返します。

from xml.etree import ElementTree as ET

tree = ET.parse('ex-1.xml')

feed = urllib.urlopen(
          'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)

ElementTree インスタンスが得られたら、getroot() メソッドでルートの Element ノードを取得できます。

文字列リテラルを受け取り、ElementTree ではなく Element ノードを返す XML() 関数もあります。 XML リテラルに近い手軽さで、XML の断片をコードへ組み込めます。

svg = ET.XML("""<svg width="10px" version="1.0">
             </svg>""")
svg.set('height', '320px')
svg.append(elem1)

個々の XML 要素はいくつかの辞書のような、いくつかのリストのようなメソッドをサポートしています。辞書的な操作は属性値のアクセスに使い、リスト的な操作は子ノードのアクセスに使います。

演算

結果

elem[n]

n 番目の子要素を返す。

elem[m:n]

m 番目から n 番目までの子要素を返す(---訳注: n は含まない---)。

len(elem)

子要素数を返す。

list(elem)

子要素のリストを返す。

elem.append(elem2)

elem2 を子として追加する。

elem.insert(index, elem2)

指定された位置に elem2 を挿入する。

del elem[n]

n 番目の子要素を削除する。

elem.keys()

属性名のリストを返す。

elem.get(name)

属性 name の値を返す。

elem.set(name, value)

属性 name に新しい値をセットする。

elem.attrib

属性を含んだ辞書を取り出す。

del elem.attrib[name]

属性 name を削除する。

コメントや処理命令も Element ノードで表されます。 ノードがコメントか処理命令かを確認するには、次のようにします。

if elem.tag is ET.Comment:
    ...
elif elem.tag is ET.ProcessingInstruction:
    ...

XML を出力するには、xml.etree.ElementTree.ElementTree.write() メソッドを呼び出してください。 parse() と同様に、文字列またはファイル風オブジェクトを受け取ります。

# エンコーディングは US-ASCII
tree.write('output.xml')

# エンコーディングは UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')

(警告: 出力に使われるデフォルトエンコーディングは ASCII です。一般的な XML での作業では要素名に任意の Unicode 文字を含められるので、ASCII エンコーディングはあまり役に立ちません。要素名に 127 より大きなどんな文字が含まれても例外となりますので。ですから任意の Unicode 文字を扱うために UTF-8 のようなエンコーディングを指定するのが吉です。)

このセクションでは ElementTree インターフェイスのほんの一部しか記載していません。さらに詳しい情報については、パッケージの公式ドキュメントを参照して下さい。

hashlib パッケージ

Gregory P. Smith が書いた新しい hashlib モジュールが、md5 と sha の代わりとして追加されました。 hashlib では、さらに SHA-224、SHA-256、SHA-384、SHA-512 という安全なハッシュもサポートします。 利用可能なら OpenSSL を使い、プラットフォーム向けに最適化された高速な実装でアルゴリズムを実行します。

後方互換性のため、古い md5 と sha モジュールも hashlib のラッパーとして残っています。 新しいモジュールのインターフェースは以前のものに非常に近いですが、完全に同じではありません。 主な違いは、新しいハッシュオブジェクトを作るコンストラクター関数の名前です。

# 従来の書き方
h = md5.md5()
h = md5.new()

# 新しい書き方
h = hashlib.md5()

# 従来の書き方
h = sha.sha()
h = sha.new()

# 新しい書き方
h = hashlib.sha1()

# 以前は使えなかったハッシュ
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()

# 別の書き方
h = hashlib.new('md5')          # アルゴリズムを文字列で指定

ハッシュオブジェクトを作った後のメソッドは従来と同じです。 update(string) は指定した文字列をハッシュ処理して現在のダイジェスト状態に反映し、digest() と hexdigest() はダイジェスト値をバイナリ文字列または十六進数字の文字列として返します。 copy() は、同じダイジェスト状態の新しいハッシュオブジェクトを返します。

参考

hashlib モジュールについてのドキュメント。

sqlite3 パッケージ

組み込みデータベース SQLite のラッパーである pysqlite モジュール (https://www.pysqlite.org) が、sqlite3 というパッケージ名で標準ライブラリに加わりました。

SQLite は、軽量なディスク上のデータベースを提供する C ライブラリです。別のサーバプロセスを用意する必要なく、 SQL クエリー言語の非標準的な一種を使用してデータベースにアクセスできます。一部のアプリケーションは内部データ保存に SQLite を使えます。また、SQLite を使ってアプリケーションのプロトタイプを作り、その後そのコードを PostgreSQL や Oracle のような大規模データベースに移植するということも可能です。

pysqlite は Gerhard Häring によって書かれ、 PEP 249 に記述された DB-API 2.0 仕様に準拠した SQL インターフェースを提供するものです。

ソースコードから Python をビルドする場合は注意してください。Python ソースツリーは SQLite コードを含まずラッパーモジュールのみを含んでいます。Python ビルド前に SQLite ライブラリとヘッダをインストールする必要があります。必要ヘッダが利用可能となっていればモジュールはビルドされます。

このモジュールを使うには、まずデータベースを表す Connection オブジェクトを作成します。 ここでは /tmp/example ファイルにデータを格納します。

conn = sqlite3.connect('/tmp/example')

特別な名前である :memory: を使うと RAM 上にデータベースを作ることもできます。

Connection が得られたら、Cursor オブジェクトを作り、その execute() メソッドで SQL コマンドを実行できます。

c = conn.cursor()

# テーブルを作成
c.execute('''create table stocks
(date text, trans text, symbol text,
 qty real, price real)''')

# データを 1 行挿入
c.execute("""insert into stocks
          values ('2006-01-05','BUY','RHAT',100,35.14)""")

たいてい、SQL 操作は Python 変数の値を使う必要があります。この時、クエリーを Python の文字列操作を使って構築することは、安全とは言えないので、すべきではありません。そのようなことをするとプログラムが SQL インジェクション攻撃に対し脆弱になりかねません。

代わりに DB-API のパラメーター置換を使ってください。 値を使う場所にはプレースホルダー ? を置き、値のタプルをカーソルの execute() メソッドの第 2 引数に渡します。 (別のデータベースモジュールでは、%s や :1 などのプレースホルダーを使う場合もあります。) 例えば次のようにします。

# これは絶対にしないこと -- 安全でない!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)

# 代わりにこうする
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)

# より大きな例
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
          ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
          ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
         ):
    c.execute('insert into stocks values (?,?,?,?,?)', t)

SELECT 文を実行した後にデータを取得するには、カーソルをイテレータとして使うか、fetchone() メソッドで該当する行を一つ取得するか、fetchall() で該当する行のリストを取得します。

以下の例ではイテレータの形を使います:

>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
...    print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>

SQLite でサポートされる SQL 方言についてもっと詳しく知りたければ、 http://www.sqlite.org を参照して下さい。

参考

https://www.pysqlite.org

pysqlite のウェブページ。

https://www.sqlite.org

SQLite のウェブページ。ここの文書ではサポートされる SQL 方言の文法と使えるデータ型を説明しています。

sqlite3 モジュールについてのドキュメント。

PEP 249 - Database API Specification 2.0

Marc-Andre Lemburg により書かれた PEP。

wsgiref パッケージ

Web Server Gateway Interface (WSGI) v1.0 は、 Web サーバと Python で記述された Web アプリケーションとの標準インターフェースであり、 PEP 333 で定義されています。 wsgiref パッケージは WSGI 仕様のリファレンス実装です。

パッケージには WSGI アプリケーションとして動作する基礎的な HTTP サーバが含まれています; このサーバは製品ユースではないデバッグ目的に有用です。サーバをセットアップするには僅か数行で済みます:

from wsgiref import simple_server

wsgi_app = ...

host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()

参考

https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/

WSGI 関連のリソースについて集約しているウェブサイト。

PEP 333 - Python Web Server Gateway Interface v1.0

PEP 著 Phillip J. Eby.

ビルドならびに C API の変更

Python のビルド過程と C API の変更は以下の通りです:

  • Python ソースツリーは CVS から Subversion に変換されました。この複雑な移行手続きは Martin von Löwis によって指揮されつつがなく遂行されました。この手続きは PEP 347 にて開発されました。

  • Prevent というソースコード解析ツールを販売する Coverity 社が、Python のソースコードを調べた結果を提供しました。 約 60 件のバグが見つかり、速やかに修正されました。 多くは参照カウントの問題で、エラー処理のコードで起きることが多いものでした。 統計は https://scan.coverity.com を参照してください。

  • C API の最大の変更は PEP 353 によるもので、インタープリタが int の代わりに Py_ssize_t という型定義を使うようになりました。 詳しくは前述の PEP 353: 添え字型に ssize_t を使う を参照してください。

  • バイトコードコンパイラーの設計が大きく変わり、構文解析木を走査して直接バイトコードを生成しなくなりました。 代わりに構文解析木を抽象構文木 (AST) に変換し、そちらを走査してバイトコードを生成します。

    Python コードからは、組み込みの compile() を使い、flags パラメーターに _ast.PyCF_ONLY_AST を指定すると AST オブジェクトを取得できます。

    from _ast import PyCF_ONLY_AST
    ast = compile("""a=0
    for i in range(10):
        a += i
    """, "<string>", 'exec', PyCF_ONLY_AST)
    
    assignment = ast.body[0]
    for_loop = ast.body[1]
    

    AST のコードにはまだ公式な文書がありませんが、PEP 339 で設計が説明されています。 コードを学び始めるには、Parser/Python.asdl の各種 AST ノードの定義を読んでください。 Python スクリプトがこのファイルを読み、Include/Python-ast.h に C の構造体定義を生成します。 Include/pythonrun.h で定義された PyParser_ASTFromString() と PyParser_ASTFromFile() は、Python のソースを受け取り、その内容を表す AST のルートを返します。 この AST は PyAST_Compile() でコードオブジェクトに変換できます。 詳しく知りたい場合はソースコードを読み、その後 python-dev で質問してください。

    AST のコードは Jeremy Hylton の指揮で開発され、Brett Cannon、Nick Coghlan、Grant Edwards、John Ehresman、Kurt Kaiser、Neal Norwitz、Tim Peters、Armin Rigo、Neil Schemenauer (アルファベット順)、および PyCon などのカンファレンスで行われた AST スプリントの参加者たちが実装しました。

  • PyCon DC 2005 の講演で初めて紹介された、Evan Jones の obmalloc パッチが適用されました。 Python 2.4 は小さいオブジェクトを 256K のアリーナに割り当てていましたが、アリーナを解放することはありませんでした。 このパッチによって、空になったアリーナは解放されるようになります。 その結果、一部のプラットフォームでは、多数のオブジェクトを割り当てた後に削除すると、Python のメモリ使用量が実際に減り、メモリが OS に返されることがあります。 (Evan Jones が実装し、Tim Peters が手を加えました。)

    この変更に伴い、拡張モジュールではメモリの割り当てにいっそう注意する必要があります。 Python の API には多数のメモリ割り当て関数があり、いくつかの系統に分かれています。 例えば PyMem_Malloc()、PyMem_Realloc()、PyMem_Free() は生のメモリを割り当てる系統で、PyObject_Malloc()、PyObject_Realloc()、PyObject_Free() は Python オブジェクトの作成に使う系統です。

    Previously these different families all reduced to the platform's malloc() and free() functions. This meant it didn't matter if you got things wrong and allocated memory with the PyMem function but freed it with the PyObject function. With 2.5's changes to obmalloc, these families now do different things and mismatches will probably result in a segfault. You should carefully test your C extension modules with Python 2.5.

  • ビルトインの集合型のために公式の C API が作られました。新しく作るのには PySet_New() か PyFrozenSet_New() を、要素の追加には PySet_Add() 、削除には PySet_Discard() 、 PySet_Contains() と PySet_Size() で集合オブジェクトの状態を調べます。 (Contributed by Raymond Hettinger.)

  • C コードから Python インタプリタの正確なリビジョンについての情報を取得出来るようになりました。 Py_GetBuildInfo() 関数を呼び出すことでビルド情報についての文字列が "trunk:45355:45356M, Apr 13 2006, 07:42:19" のように返ります。 (Contributed by Barry Warsaw.)

  • Two new macros can be used to indicate C functions that are local to the current file so that a faster calling convention can be used. Py_LOCAL declares the function as returning a value of the specified type and uses a fast-calling qualifier. Py_LOCAL_INLINE does the same thing and also requests the function be inlined. If macro PY_LOCAL_AGGRESSIVE is defined before python.h is included, a set of more aggressive optimizations are enabled for the module; you should benchmark the results to find out if these optimizations actually make the code faster. (Contributed by Fredrik Lundh at the NeedForSpeed sprint.)

  • PyErr_NewException(name, base, dict) が base 引数としてベースクラスのタプルを受け付けるようになりました。 (Contributed by Georg Brandl.)

  • 警告を出す PyErr_Warn() 関数は非推奨となり、代わりに PyErr_WarnEx(category, message, stacklevel) を使います。 この関数では、警告の対象とする呼び出し元までのスタックフレーム数を指定できます。 stacklevel が 1 なら PyErr_WarnEx() を呼んだ関数、2 ならその上の関数というようになります。 (Neal Norwitz が追加しました。)

  • CPython は今でも C で書かれていますが、コードは C++ コンパイラでもエラーなしでコンパイル出来るようになりました。 (Implemented by Anthony Baxter, Martin von Löwis, Skip Montanaro.)

  • PyRange_New() 関数が削除されました。 一度も文書化されず、コアのコードでも使われておらず、エラーチェックも危険なほど緩いものでした。 可能性は低いものの、拡張モジュールで使っていた場合は、次のようなコードで置き換えられます。

    range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
                                  start, stop, step);
    

ポート特有の変更

  • MacOS X (10.3 以上): モジュールの動的ロードに、MacOS 固有の関数ではなく dlopen() 関数を使うようになりました。

  • MacOS X: configure スクリプトに --enable-universalsdk オプションが加わりました。 PowerPC と Intel の両プロセッサーで動作するユニバーサルバイナリとしてインタープリタをコンパイルします。 (Ronald Oussoren による貢献です。bpo-2573。)

  • Windows: .dll はもはや拡張モジュールのファイル拡張子としてはサポートされません。これからは .pyd だけが拡張モジュールとして検索されるファイル拡張子です。

Python 2.5 への移植

このセクションでは前述の変更により必要となるかもしれないコードの変更を列挙します:

  • ASCII がモジュールのデフォルトエンコーディングになっています(訳注: Python 3 からはデフォルトは utf-8 (PEP 3120))。8 ビット文字を含んでいるのにエンコーディング宣言がないモジュールが構文エラーになるようになりました。Python 2.4 では構文エラーとはならず警告でした。

  • これまでジェネレータの gi_frame 属性は常にフレームオブジェクトでした。 PEP 342: ジェネレータの新機能 で説明した PEP 342 の変更により、gi_frame が None になることがあります。

  • Unicode 文字列とデフォルトの ASCII エンコーディングで Unicode に変換出来ない 8 ビット文字列との比較を試みると、新しい警告 UnicodeWarning が引き起こされるようになっています。以前はそのような比較では UnicodeDecodeError 例外を起こしていました。

  • ライブラリ: csv モジュールは引用符内のマルチラインをより厳密に扱うようになっています。フィールド内に改行を埋め込んでいるファイルがある場合は、その入力は改行文字を残すやり方で行分解されるはずです。

  • ライブラリ: locale モジュールの format() 関数は、以前は %文字指定子が一つを超えてさえいなければ任意の文字列を受け付けていたかもしれませんが、Python 2.5 からは正確に一つの、ほかに周りをテキストで囲まれていない %文字指定子でなければなりません。

  • ライブラリ: pickle と cPickle モジュールは、__reduce__() メソッドの戻り値として None を受け付けなくなりました。 代わりに引数のタプルを返す必要があります。 また、非推奨だったキーワード引数 bin も受け付けなくなりました。

  • Library: The SimpleXMLRPCServer and DocXMLRPCServer classes now have a rpc_paths attribute that constrains XML-RPC operations to a limited set of URL paths; the default is to allow only '/' and '/RPC2'. Setting rpc_paths to None or an empty tuple disables this path checking.

  • C API: 64 ビットマシンでより多くのデータを処理できるよう、多数の関数が int の代わりに Py_ssize_t を使うようになりました。 警告を避け、64 ビットマシンに対応するために、拡張コードにも同じ変更が必要になる場合があります。 詳しくは前述の PEP 353: 添え字型に ssize_t を使う を参照してください。

  • C API: obmalloc の変更により、PyMem_* 系と PyObject_* 系の関数を混在させないよう注意する必要があります。 一方の系統の *_Malloc で割り当てたメモリは、同じ系統の *_Free 関数で解放しなければなりません。

謝辞

本稿の草稿に対して提案、訂正、支援を提供してくださった次の方々に感謝します。 Georg Brandl、Nick Coghlan、Phillip J. Eby、Lars Gustäbel、Raymond Hettinger、Ralf W. Grosse-Kunstleve、Kent Johnson、Iain Lowe、Martin von Löwis、Fredrik Lundh、Andrew McNamara、Skip Montanaro、Gustavo Niemeyer、Paul Prescod、James Pryor、Mike Rovner、Scott Weikart、Barry Warsaw、Thomas Wouters。