What’s New in Python 2.5¶
著者: | A.M. Kuchling |
---|
この文書は Python 2.5 の新機能について解説します。 Python 2.5 の最終リリースは 2006 年 8 月にスケジュールされました。PEP 356 が予定されたリリーススケジュールを記述しています。
Python 2.5 の変更は言語とライブラリの改善の面白い組み合わせになりました。ライブラリの強化のほうが Python ユーザコミュニティにとっては重要でしょう。多数の大変利用価値の高いパッケージが追加されました。新しいモジュールとしては、XML 処理のための ElementTree (xml.etree
)、SQLite データベースのためのモジュール(sqlite
)、そして 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 つの例を考えてみてください:
# First version -- no parens
level = 1 if logging else 0
# Second version -- with parens
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):
"Write the contents of 'message' to the specified subsystem."
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()
は包まれるほうの名前、モジュール、ドキュメンテーション文字列属性をラッパー関数にコピーすることで、トレースバックを理解しやすくします。たとえばこう書けます:
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),
)
Another new enhancement to the Python package index at https://pypi.python.org is storing source and binary archives for a package. The new upload Distutils command will upload a package to the repository.
パッケージがアップロードされる前には、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 module import names
文において、 names を丸括弧で囲むことが出来るようにすることで、たくさんの名前をインポートしやすくしました。
より複雑なほうは Python 2.5 で実装されました: モジュールのインポートにおいて、それが絶対インポートなのかパッケージ相対のインポートなのかを指定出来るようにする、というものです。将来のバージョンの Python では絶対インポートをデフォルトにする方向に向かう予定です。
いま、あなたは以下のようなパッケージディレクトリを持っているとします:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
pkg
パッケージがモジュール pkg.main
とサブモジュール pkg.string
を持っています。
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
形式を使う際にモジュール名の前にピリオドを付ければまだ可能です:
# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string
これは現在のパッケージからの相対で string
モジュールをインポートしますので、 pkg.main
内ではこれは、 name1 と name2 を pkg.string
からインポートするでしょう。加えて、先行する複数ピリオドは、現在のパッケージの親からの相対インポートを実行します。例えば、 A.B.C
モジュール内のコードはこのように出来ます:
from . import D # Imports A.B.D
from .. import E # Imports A.E
from ..F import G # Imports A.F.G
このピリオドによる書き方は import modname
形式のインポート文では使えず、 from ... import
形式でのみ使えます。
参考
- PEP 328 - マルチラインインポートと、絶対/相対インポート
- PEP 著 Aahz; 実装 Thomas Wouters。
- https://pylib.readthedocs.org/
- Holger Krekel による py ライブラリで、
py.std
パッケージを含みます。
PEP 338 - モジュールをスクリプトとして実行する¶
Python 2.4 で追加されたモジュールをスクリプトとして実行するための -m
スイッチが、少し能力を高めました。Python インタプリタ内での C 実装に代わり、これの実現には新しいモジュール runpy
を使うようになっています。
runpy
モジュールはインポートのメカニズムをより洗練された方法で実装しているので、今では pychecker.checker
のようにパッケージ内のモジュールも実行出来ます。このモジュールは異なるインポートメカニズム、例えば zipimport
モジュールもサポートします。このことにより、 sys.path
に .zip アーカイブのパスを追加して、 -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 から 10 までの値を返すイテレータです。 yield
文 (statement) に出会うと、そのイテレータは準備された値を返して、ローカル変数は保存しつつ関数の実行は一時停止します。続くイテレータの next()
メソッド呼び出しによって実行がその yield
文の次から再開します。
Python 2.3 では yield
は文 (statement) でした。しかるにそれでは値を返しません。Python 2.5 で yield
は式 (expression) になりました。値を返すわけですから、変数に代入出来ますし、ほかの演算に使えます:
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 value provided, change counter
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()
のほかにも新しいメソッドが二つあります
throw(type, value=None, traceback=None)
はジェネレータ内で例外を投げるために使います; その例外はジェネレータの実行が停止したところのyield
式によって投げられます。close()
はジェネレータ内でGeneratorExit
例外を投げてイテレートを終了させます。この例外を受け取ったジェネレータのコードはGeneratorExit
かStopIteration
を投げなくてはいけません; この例外を捕捉して何かほかのことをしようとするのは規則違反であり、RuntimeError
を引き起こします; 関数が何かほかの例外を投げると、その例外は呼び出し元に伝播します。close()
はジェネレータのガーベージコレクトによっても呼ばれます。GeneratorExit
が起こったときにクリーンアップ作業をする必要があるなら、GeneratorExit
を捕捉するのではなくtry: ... finaly:
するようお勧めします。
これらの変更の合わせ技で、ジェネレータは情報の一方的な生産者から、生産者かつ消費者という存在に変貌を遂げたのです。
ジェネレータは コルーチン という、より一般化された形式のサブルーチンにもなります。サブルーチンは一カ所 (関数の冒頭) から入って別の一カ所 (return
文) から出るだけですが、コルーチンはいろいろな場所 (yield
文) から入ったり出たり再開したりできるのです。わたしたちは Python でコルーチンを効果的に使うためのパターンを理解する必要があります。
close()
メソッドの追加には、自明とは言えない副作用が一つあります。 close()
はジェネレータがガーベージコレクトされる際に呼ばれるので、ジェネレータコードはジェネレータが破棄される前に、一つ動くラストチャンスを持つのです。このラストチャンスは、ジェネレータ内の try...finally
ステートメントがもはや必ず動けることを意味しています; finally
節は必ず実行の機会を得ます。 try...finally
と yield
を組み合わせられないという構文的な制限は、それゆえに取り除かれました。これは小さな言語の取るに足らないことのように見えますが、ジェネレータの使用と try...finally
は PEP 343 で記述される with
ステートメントの実装のために実際に必要です。この新しいステートメントについては続くセクションで見ていきましょう。
もう一つさらに深遠なこの変更の効果: 以前はジェネレータの gi_frame
属性は常にフレームオブジェクトでした。今では gi_frame
は、ジェネレータが使い果たされた場合に None
になります。
参考
- PEP 0342 - 拡張されたジェネレータを用いたコルーチン
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 エントリ。
- 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
expression は評価されて結果がコンテキスト管理プロトコルをサポートするオブジェクトにならなければなりません (具体的にはメソッド __enter__()
と __exit__()
を持つオブジェクト)。 ( 訳注: Python ドキュメント全体で context manager protocol と context management protocol とで不統一。同じものです。 )
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
ループが道半ばにして例外と成り果てても、自動的にクローズされます。
注釈
このケースでは、 f は open()
が作ったオブジェクトと同じです。これはファイルオブジェクトの file.__enter__()
が self を返しているからです。
threading
モジュールのロック・条件変数でも 'with
' ステートメントの恩恵にあずかれます:
lock = threading.Lock()
with lock:
# Critical section of code
...
ブロックが実行される前にロックが獲得されて、ブロックが完了するやいなや必ず解放されます。
decimal
モジュール内の新しい localcontext()
関数は現在の decimal のコンテキスト (計算の望みの精度と丸め特性をカプセル化しています) を保存しておいてあとで元に戻すのを簡単にしてくれます:
from decimal import Decimal, Context, localcontext
# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# All code in this block uses a precision of 16 digits.
# The original context is restored on exiting the block.
print v.sqrt()
コンテキストマネージャを書く¶
中身を紐解いてみれば、 'with
' ステートメントはけっこう入り組んでいます。ほとんどの人にとっては、既存のオブジェクトを 'with
' とともに使うだけのことでその詳細は知らなくても良いので、そうしたいならこのセクションの残りの部分は読み飛ばして結構です。新しいオブジェクトの作者は基礎となる実装の詳細について知る必要があります。このまま読み進めるべきです。
コンテキスト管理プロトコルの高度な説明はこんなです:
- expression は評価されて、 "コンテキストマネージャ(context manager)" にならなければなりません。コンテキストマネージャは
__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 ...')
# ... more operations ...
トランザクションはブロック内のコードがつつがなく終了すればコミットし、例外が発生すればロールバックすべきです。私が思い描いている DatabaseConnection
の基本的なインターフェイスはこんなです:
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
__enter__()
メソッドはとっても簡単で、トランザクションを開始する必要があるだけです。このアプリケーションでは、カーソルオブジェクトを結果とすることが有用なので、メソッドはそれを返しましょう。ユーザはこれにより as cursor
をその 'with
' ステートメントにつけて、そのカーソルを変数名に束縛できます:
class DatabaseConnection:
...
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
__exit__()
メソッドはそれがほとんどの仕事をしなければならない場所なので、もっと複雑です。メソッドは例外が起こったのかどうかをチェックし、例外が起こっていなければトランザクションをコミットし、例外があればロールバックしなければいけません。
下記のコード内では実行がメソッドの末尾まで落ちていって、なのでデフォルトの None
返却になります。 None
は偽なので、例外は自動的に再送出されます。望むならもっと明示的に、コメントでマークした部分で return
文を書いてもよろしいです:
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
contextlib モジュール¶
新しい contextlib
モジュールは、 'with
' ステートメントで使えるオブジェクトを書く際に便利ないくつかの関数とデコレータを提供しています。
デコレータは contextmanager()
という名前で、新たにクラスを書く代わりに一つジェネレータを書けば済むようにするものです。そのジェネレータは正確に一つの値を yield しなければなりません。 yield
より上の部分のコードが __enter__()
メソッドとして実行されます。yield した値は __enter__()
メソッドの戻り値となって、 '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 # New in Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions)
この再編成が行われたのは、人々がしばしばプログラムのエラーを示す例外すべてを捕捉したがるからです。 KeyboardInterrupt
と SystemExit
はエラーではありませんが、普通は Control-C
をユーザが叩いたか、コードが sys.exit()
を呼び出したかのような明示的なアクションを表します。剥き出しの except:
はまさに全ての例外を捕捉しますから、一般に、再送出のために KeyboardInterrupt
と SystemExit
はリストする必要があります。お決まりのパターンはこんなです:
try:
...
except (KeyboardInterrupt, SystemExit):
raise
except:
# Log error...
# Continue running program...
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 ビットプラットフォームでは今でも int
を 32 ビット型として定義していますので、リストは 2**31 - 1
= 2147483647 までしか保持出来なかった、ということです。(実際には 64 ビットコンパイラが使える小数の異なったプログラミングモデルもあります – http://www.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 ビット機での非互換性をもたらすので、64 ビットユーザが比較的少数派である間は、今のところ漸近的推移で合意されました。 (5 年もしくは 10 年の間には 全て が 64 ビット機であるかもしれませんので、この漸近的推移はより苦痛になるかもしれません。) — (—訳注: 16 GiB はどこから出てくる? 2147483647*4 と 2147483647*8 の間らしいが…。このセクション全体として、誤解か説明不足かどちらかです。 ssize_t として 64 ビットプラットフォームで 64 ビットアドレス空間を目いっぱい使える、このセクションはそれだけを言えばいいはずなのですが…。それと「漸近的推移」(transition)についてですが、これはこの変更の意図としては続く文の「まだ int のものがいる」ことを指しているのですが、文章の構造から考えると、この著者は「32 ビット機でさえ 64 ビットにするのが理想だ」を含意していたのではないかという気がします。—)
この変更は C 拡張モジュールの著者に大変大きく影響します。Python 文字列とリストやタプルのようなコンテナ型は、そのサイズを表すのに Py_ssize_t
を使うようになっています。 PyList_Size()
のような関数は Py_ssize_t
を返します。拡張モジュール内のコードでは、ですので、ある程度の変数の Py_ssize_t
への変更が必要でしょう。
PyArg_ParseTuple()
関数と Py_BuildValue()
関数は新しい変換コード n
を Py_ssize_t
のために持ちました。 PyArg_ParseTuple()
の s#
と t#
はデフォルトではまだ int
を出力しますが、 PY_SSIZE_T_CLEAN
を定義することが出来ます。 Python.h
インクルード前に定義してください。 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
を送出します。
これに呼応する nb_index
スロットが C レベルの PyNumberMethods
構造体に追加され、C 拡張はこれでこのプロトコルを実装出来ます。 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] # Prints 1, 2 print d[3], d[4] # Prints 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'] # Prints 'longest' print max(L, key=len) # Prints 'short', because lexicographically 'short' has the largest value 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)
を使うようです (これはお奨めしませんが)。 (—訳注: 不思議な論法で意味がわかりません。id が非負を返すとなぜユーザは __hash__ の実装に使おうとするのか? ユーザがそれをしてしまうのは単にデフォルト実装がそうだから、というだけではないかと思います。__cmp__, __eq__ が「身元」以外の意味を使って比較を行うならば、 __cmp__ で id を使うのはシンプルに「ダメ」でしょう。–)モジュールのデフォルトエンコーディングが ASCII になりました(訳注: Python 3 からはデフォルトは utf-8 (PEP 3120))。8 ビット文字を含んでいるのにエンコーディング宣言がないモジュールが構文エラーになるようになりました。Python 2.4 では構文エラーとはならず警告でした。モジュールのエンコーディングをする方法については PEP 263 を参照してください; 例えば、ソースコードの先頭付近にこのような行を追加することで出来ます:
# -*- coding: latin1 -*-
Unicode 文字列とデフォルトの ASCII エンコーディングで Unicode に変換出来ない 8 ビット文字列との比較を試みると、新しい警告
UnicodeWarning
が引き起こされるようになっています。比較結果は偽です:>>> chr(128) == unichr(128) # Can't convert chr(128) to 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) can be converted 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.)
最適化¶
Several of the optimizations were developed at the NeedForSpeed sprint, an event held in Reykjavik, Iceland, from May 21–28 2006. The sprint focused on speed enhancements to the CPython implementation and was funded by EWT LLC with local support from CCP Games. Those optimizations added at this sprint are specially marked in the following list.
- When they were introduced in Python 2.4, the built-in
set
andfrozenset
types were built on top of Python’s dictionary type. In 2.5 the internal data structure has been customized for implementing sets, and as a result sets will use a third less memory and are somewhat faster. (Implemented by Raymond Hettinger.) - The speed of some Unicode operations, such as finding substrings, string splitting, and character map encoding and decoding, has been improved. (Substring search and splitting improvements were added by Fredrik Lundh and Andrew Dalke at the NeedForSpeed sprint. Character maps were improved by Walter Dörwald and Martin von Löwis.)
- The
long(str, base)
function is now faster on long digit strings because fewer intermediate results are calculated. The peak is for strings of around 800–1000 digits where the function is 6 times faster. (Contributed by Alan McIntyre and committed at the NeedForSpeed sprint.) - It’s now illegal to mix iterating over a file with
for line in file
and calling the file object’sread()
/readline()
/readlines()
methods. Iteration uses an internal buffer and theread*()
methods don’t use that buffer. Instead they would return the data following the buffer, causing the data to appear out of order. Mixing iteration and these methods will now trigger aValueError
from theread*()
method. (Implemented by Thomas Wouters.) - The
struct
module now compiles structure format strings into an internal representation and caches this representation, yielding a 20% speedup. (Contributed by Bob Ippolito at the NeedForSpeed sprint.) - The
re
module got a 1 or 2% speedup by switching to Python’s allocator functions instead of the system’smalloc()
andfree()
. (Contributed by Jack Diederich at the NeedForSpeed sprint.) - The code generator’s peephole optimizer now performs simple constant folding
in expressions. If you write something like
a = 2+3
, the code generator will do the arithmetic and produce code corresponding toa = 5
. (Proposed and implemented by Raymond Hettinger.) - Function calls are now faster because code objects now keep the most recently finished frame (a "zombie frame") in an internal field of the code object, reusing it the next time the code object is invoked. (Original patch by Michael Hudson, modified by Armin Rigo and Richard Jones; committed at the NeedForSpeed sprint.) Frame objects are also slightly smaller, which may improve cache locality and reduce memory usage a bit. (Contributed by Neal Norwitz.)
- Python’s built-in exceptions are now new-style classes, a change that speeds up instantiation considerably. Exception handling in Python 2.5 is therefore about 30% faster than in 2.4. (Contributed by Richard Jones, Georg Brandl and Sean Reifschneider at the NeedForSpeed sprint.)
- Importing now caches the paths tried, recording whether they exist or not so
that the interpreter makes fewer
open()
andstat()
calls on startup. (Contributed by Martin von Löwis and Georg Brandl.)
新たなモジュール、改良されたモジュール、削除されたモジュール¶
標準ライブラリは Python 2.5 で数多くの拡張とバグフィックスを行っています。ここでは注目に値する変更をモジュール名の辞書順で列挙します。変更についてのもっと完全なリストが見たければソースツリーの Misc/NEWS
を調べるか、全ての詳細について SVN ログに目を通してみてください。
audioop
モジュールに a-LAW エンコーディングのサポートが追加され、また、u-LAW エンコーディングのコードも改善されています。 (Contributed by Lars Immisch.)codecs
モジュールに漸増的コーデックのサポートが追加されています。codec.lookup()
関数がタプルではなくCodecInfo
を返すようになっています。CodecInfo
のインスタンスは後方互換性を維持するために 4 要素タプルのように振舞うだけでなく、属性encode
,decode
,incrementalencoder
,incrementaldecoder
,streamwriter
,streamreader
を持ちます。漸増的コーデックは入力を受け取って出力するのを複数チャンクに分けて行えます; 出力は非漸増的コーデックに一回で入力全体を渡したものと同じになります。詳細はcodecs
モジュールのドキュメントを参照して下さい。 (Designed and implemented by Walter Dörwald.)collections
モジュールに新たに追加されたdefaultdict
型は、標準dict
のサブクラスです。この新しい型はほとんど辞書と同じに振る舞い、ただし、キーを要求された際にそのキーが存在していなかった場合に、自動的に辞書にデフォルト値を追加します。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
モジュールで提供されている両端キュー (double-ended queue) 型deque
に、キュー内で最初に現れる value を削除するメソッドremove(value)()
メソッドが追加されています。 value が見つからなければValueError
が送出されます。 (Contributed by Raymond Hettinger.)新規モジュール:
contextlib
モジュールには 'with
' ステートメントで使えるヘルパ関数が含まれています。詳細は contextlib モジュール をみてください。新規モジュール:
cProfile
モジュールは既存のprofile
モジュールの C 実装で、遥かに小さなオーバヘッドで実行出来ます。モジュールのインターフェイスはprofile
と同じです: 関数をプロファイルするのにはcProfile.run('main()')
と実行し、プロファイル結果をファイルに書き出すなど出来ます。これは Hotshot プロファイラとして知られるものではないですが (これも C で書かれてますがprofile
モジュールのインターフェイスとは別物です)、将来バージョンの Python で保守が続けられる予定です。(Contributed by Armin Rigo.)また、プロファイラによる計測データの解析のための
pstats
モジュールが、Stats
コンストラクタの stream 引数による直接ファイル出力に対応しました。 (Contributed by 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.)
The
datetime
class in thedatetime
module now has astrptime(string, format)
method for parsing date strings, contributed by Josh Spoerri. It uses the same format characters astime.strptime()
andtime.strftime()
:from datetime import datetime ts = datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
difflib
モジュールのメソッドSequenceMatcher.get_matching_blocks()
が、合致するサブシーケンスを記述するブロックについて、最小範囲リストを返すよう保障するようになりました。以前は時折 2 つのリストエントリに合致要素ブロックが分割されることがありました。(Enhancement by Tim Peters.)doctest
モジュールに、実行されるべきものから例を守るSKIP
オプションが追加されています。これは、読者のための使用例として意図しているけれども実際のテストケースとして意図していないようなコードスニペットのために用意されました。testfile()
関数とDocFileSuite
にファイルのエンコーディングを指定するための encoding パラメータが追加されました。これにより docstring 内に非 ASCII 文字列を含むテストが簡単になります。(Contributed by Bjorn Tillenius.)email
パッケージがバージョン 4.0 にアップデートされました (Contributed by Barry Warsaw.)fileinput
モジュールがさらに柔軟性を持つようになりました。Unicode ファイル名がサポートがサポートされるようになりました。input()
関数に mode パラメータが追加されました。これは"r"
がデフォルトで、バイナリとして読み込みことも出来ますし、 universal newlines モードも使えます。もう一つの新しいパラメータ openhook で、ファイルを開くのにopen()
の代わりのものを使えます。ファイル集合のイテレートでは、FileInput
オブジェクトのfileno()
が現在開いているファイルのファイル記述子を返します。 (Contributed by Georg Brandl.)gc
モジュールに、新しい関数get_count()
が追加されています。これは GC 3 世代についての現在の検出を含む 3 要素タプルを返します。これはガーベージコレクタの決算情報です; これらの数が指定された閾値に到達すると、ガーベージコレクトのスイープが起こります。既存のgc.collect()
関数は省略可能な generation 引数を取るようになっていて、これはどの世代を検出するかを指定する 0、1、2 です。 (Contributed by Barry Warsaw.)heapq
モジュールのnsmallest()
関数とnlargest()
関数がキーワードパラメータkey
をサポートするようになっています。これはmin()
/max()
関数とsort()
メソッドで提供されているものと似たものです。例えば:>>> import heapq >>> L = ["short", 'medium', 'longest', 'longer still'] >>> heapq.nsmallest(2, L) # Return two lowest elements, lexicographically ['longer still', 'longest'] >>> heapq.nsmallest(2, L, key=len) # Return two shortest elements ['short', 'medium']
(Contributed by Raymond Hettinger.)
itertools.islice()
関数が start と step としてNone
を受け付けるようになっています。これは slice オブジェクトとの互換性を高めるもので、つまり以下のように書くことが出来ます:s = slice(5) # Create slice object itertools.islice(iterable, s.start, s.stop, s.step)
(Contributed by Raymond Hettinger.)
locale
モジュールのformat()
関数が更新され、2 つの関数format_string()
とcurrency()
が追加されました。format()
関数の val パラメータは以前は一つ以上の %文字指定子が現れる文字列が許されていました; 今はこのパラメータは正確に一つの %文字指定子を含む、周りに囲むテキストのない文字列でなければなりません。省略可能な monetary パラメータも追加されています。これがTrue
の場合、通貨の書式化の 3 桁ごとに区切るセパレータに、ロケールのルールを使います。複数 %文字指定子を含む文字列をフォーマットするには、
format()
のように働き、任意のテキストと %文字指定子を混ぜた文字列をサポートする新しいformat_string()
関数を使ってください。現在ロケール設定に関連した数字を書式化する
currency()
関数も追加されています。(Contributed by Georg Brandl.)
mailbox
モジュールでは、メールボックスについてそれを読むことに加えて修正出来る能力を追加するための、大々的な書き換えが行われています。mbox
,MH
,Maildir
を含む新しいクラス群はメールボックス読み込みに使われますが、メッセージ追加のためのadd(message)
、削除のremove(key)
、ロック/アンロックのためのlock()
/unlock()
も持っています。続く例は maildir 形式から mbox 形式に変換する例です:import mailbox # 'factory=None' uses email.Message.Message as the class representing # individual messages. 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 インストーラの.msi
ファイルと CAB ファイルの作成をすることが出来ます。.msi
データベースの読み込みサポートもいくらか入っています。 (Contributed by Martin von Löwis.)nis
モジュールで、システムデフォルトのドメイン以外のドメインへのアクセスが可能になりました。nis.match()
とnis.maps()
に domain 引数を渡します。 (Contributed by Ben Bell.)operator
モジュールのitemgetter()
関数とattrgetter()
関数が複数フィールドをサポートするようになりました。operator.attrgetter('a', 'b')
のように呼び出すと、a
とb
属性を取り出す関数を返します。この新機能とsort()
メソッドのkey
パラメータを組み合わせると、複数フィールドでのリストのソートが簡単になります。optparse
モジュールが Optik ライブラリのバージョン 1.5.1 に更新されました。OptionParser
クラスにepilog
属性とdestroy()
メソッドが追加されています。前者はヘルプメッセージのあとに出力される文字列です。後者はオブジェクトによって作られた循環参照を破棄します。 (Contributed by Greg Ward.)os
モジュールに多数の変更がありました。stat_float_times
値のデフォルトが真となっていて、これはつまりos.stat()
が時刻の値を浮動小数点数で返すということです。(ただし必ずしもos.stat()
が秒の端数が正確な値を返すという意味ではありません; 全てのシステムがそのような精度をサポートしてはいません。)定数
os.SEEK_SET
,os.SEEK_CUR
,os.SEEK_END
が追加されました; これらはos.lseek()
関数へ渡すパラメータです。ロックに用いる 2 つの定数os.O_SHLOCK
とos.O_EXLOCK
が追加されました。2 つの新しい関数
wait3()
とwait4()
が追加されています。これらはwaitpid()
関数に似ています。これは子プロセスが終了するのを待ってプロセス ID とその終了コードを返しますが、wait3()
とwait4()
は追加の情報を返します。wait3()
はプロセス ID を入力に取りませんので任意の子プロセス終了を待ち、resource.getrusage()
関数から返る process-id, exit-status, resource-usage の 3 要素タプルを返します。wait4(pid)
はプロセス ID を取ります。 (Contributed by Chad J. Schroeder.)FreeBSD では、
os.stat()
関数がナノ秒精度の時刻を返し、また、返却オブジェクトがst_gen
とst_birthtime
を持つようになっています。st_flags
属性も、プラットフォームがサポートされている場合には利用可能です。 (Contributed by Antti Louko and Diego Pettenò.)pdb
モジュールで提供される Python デバッガが、ブレイクポイントに到達して実行が停止する際に実行するコマンドのリストを記憶するようになりました。ブレイクポイント #1 を作ったら、commands 1
を入力し、実行するコマンド群を入力し、end
でリストを終えます。コマンドリストにはcontinue
やnext
のような実行再開コマンドを含めることが出来ます。 (Contributed by Grégoire Dooms.)ライブラリ:
pickle
,cPickle
モジュールが__reduce__()
がNone
を返すことを許さなくなっています; 必ず引数のタプルを返さなければなりません。また同様に、非推奨となっていた bin キーワードパラメータも、もはや拒絶します。None
を返すことは Python 2.4 では非推奨となっていて、これにてその機能の削除は完成したことになります。パッケージ検索のための色々なユーティリティを含む
pkgutil
モジュールが、PEP 302 のインポートフックをサポートするよう拡張されて、ZIP 形式アーカイブに格納されたパッケージに対しても動作するようになりました。 (Contributed by 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 にしました。 (Contributed by Trent Mick.)The
Queue
class provided by theQueue
module gained two new methods.join()
blocks until all items in the queue have been retrieved and all processing work on the items have been completed. Worker threads call the other new method,task_done()
, to signal that processing for an item has been completed. (Contributed by Raymond Hettinger.)古い
regex
,regsub
モジュール、これは Python 2.0 からずっと非推奨になっていましたが、ついに削除されました。ほかにも、statcache
,tzparse
,whrandom
が削除されています。dircmp
やni
といった石器時代のモジュールを大事にしまっていたlib-old
ディレクトリも削除されました。lib-old
がデフォルトでsys.path
に含まれることはなかったので、あなたが明示的にそれをsys.path
に入れてこなかった限り、この削除はあなたには関係ないでしょう。rlcompleter
モジュールがreadline
モジュールのインポートに依存しないようになりました。これにより非 Unix プラットフォームで動作するようになりました。 (Patch from Robert Kiendl.)SimpleXMLRPCServer
クラスとDocXMLRPCServer
クラスに XML-RPC 操作を限られた URL パスに制限するrpc_paths
属性が追加されています; デフォルトでは'/'
と'/RPC2'
のみが許されています。rpc_paths
にNone
か空のタプルを渡すことで、このパスのチェックは無効になります。The
socket
module now supportsAF_NETLINK
sockets on Linux, thanks to a patch from Philippe Biondi. Netlink sockets are a Linux-specific mechanism for communications between a user-space process and kernel code; an introductory article about them is at https://www.linuxjournal.com/article/7356. In Python code, netlink addresses are represented as a tuple of 2 integers,(pid, group_mask)
.ソケットオブジェクトの 2 つの新たなメソッド、
recv_into(buffer)
,recvfrom_into(buffer)
は、受信データを、文字列データとして返す代わりにバッファプロトコルをサポートするオブジェクトに書き込みます。このことにより、受信データを直接 array やメモリマップドファイルに置けます。ソケットオブジェクトには
getfamily()
,gettype()
,getproto()
アクセッサメソッドも追加されています。それぞれソケットについてのアドレスファミリ、タイプ、プロトコルを取得します。新規モジュール:
spwd
モジュールは、シャドーパスワードをサポートするシステムにおいて、シャドーパスワードデータベースへのアクセスを提供します。pack()
,unpack()
メソッドでフォーマット文字列をStruct
オブジェクトにコンパイルすることで、struct
がより高速になっています。これはre
モジュールでコンパイル済み正規表現オブジェクトを作れるのに似ています。モジュールレベルのpack()
,unpack()
関数もそのまま使えます; それらはStruct
オブジェクトを作ってキャッシュします。あるいはStruct
インスタンスを直接使えます:s = struct.Struct('ih3s') data = s.pack(1972, 187, 'abc') year, number, name = s.unpack(data)
You can also pack and unpack data to and from buffer objects directly using the
pack_into(buffer, offset, v1, v2, ...)
andunpack_from(buffer, offset)
methods. This lets you store data directly into an array or a memory-mapped file.(
Struct
objects were implemented by Bob Ippolito at the NeedForSpeed sprint. Support for buffer objects was added by Martin Blais, also at the NeedForSpeed sprint.)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 (universally unique identifiers) を生成します。その RFC ではいくつかの異なる UUID のバージョンを定義しており、文字列から生成するもの、システム特性から生成するもの、純粋に乱数から生成するものがあります。このモジュールではUUID
クラスとuuid1()
,uuid3()
,uuid4()
,uuid5()
関数を持っていて、それら異なったバージョンの UUID を生成します。(UUID バージョン 2 は RFC 4122 にありませんのでこのモジュールにもないです)>>> import uuid >>> # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') >>> # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') >>> # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(Contributed by Ka-Ping Yee.)
weakref
モジュールのWeakKeyDictionary
型とWeakValueDictionary
型に、辞書内に含まれる弱参照を巡回する新たなメソッドが追加されています。iterkeyrefs()
とkeyrefs()
がWeakKeyDictionary
に追加され、itervaluerefs()
とvaluerefs()
がWeakValueDictionary
に追加されました。(Contributed by Fred L. Drake, Jr.)The
webbrowser
module received a number of enhancements. It’s now usable as a script withpython -m webbrowser
, taking a URL as the argument; there are a number of switches to control the behaviour (-n
for a new browser window,-t
for a new tab). New module-level functions,open_new()
andopen_new_tab()
, were added to support this. The module’sopen()
function supports an additional feature, an autoraise parameter that signals whether to raise the open window when possible. A number of additional browsers were added to the supported list such as Firefox, Opera, Konqueror, and elinks. (Contributed by Oleg Broytmann and Georg Brandl.)The
xmlrpclib
module now supports returningdatetime
objects for the XML-RPC date type. Supplyuse_datetime=True
to theloads()
function or theUnmarshaller
class to enable this feature. (Contributed by Skip Montanaro.)zipfile
モジュールが ZIP64 バージョンのフォーマットをサポートしました。これで 4GiB を超える zip 書庫を作れ、4GiB を超えるファイルを書庫に含めることが出来ます。 (Contributed by Ronald Oussoren.)zlib
モジュールのCompress
,Decompress
オブジェクトがcopy()
メソッドをサポートするようになりました。オブジェクトの内部状態を複製して新しいCompress
あるいはDecompress
オブジェクトを返します。 (Contributed by 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 版は全て mutable です; value
属性を介して値を代入出来ます。 Python 整数と文字列は自動的に対応する C 型に変換されますが、それ以外の型では適切な型コンストラクタを使わなければなりません。(なければなりません と言いました。間違えれば、インタプリタがセグメンテーション違反で落ちるなどしょっちゅうです。)
C 関数がメモリ領域を更新するものである場合、Python 文字列に c_char_p()
を使うべきではありません。 Python 文字列は immutable であることを前提としているからです; この規則を犯すことは頭を掻き毟るバグを引き起こすでしょう。更新可能なメモリ領域が必要な場合は 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
オブジェクトとして利用出来ます。このオブジェクトは関数呼び出し前に GIL を解放 しません 。インタプリタ内のコードを呼び出すのにロックは保持されていなければならないからです。 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 ラッパーを書き始めるでしょう,
参考
- http://starship.python.net/crew/theller/ctypes/
- ctypes のウェブページで、チュートリアル、リファレンス、FAQ があります。
ctypes
モジュールについてのドキュメント。
ElementTree パッケージ¶
XML 処理のための、Fredrik Lundh の ElementTree ライブラリのサブセットが、標準ライブラリに xml.etree
として追加されました。利用可能なモジュールは ElementTree 1.2.6 よりの ElementTree
, ElementPath
, ElementInclude
です。 C 実装 cElementTree
モジュールも含まれています。
このセクションの残りの部分は ElementTree 利用の簡単な概略について提供します。完全なドキュメントは http://effbot.org/zone/element-index.htm より利用可能です。
ElementTree は XML ドキュメントを、要素ノードのツリーとして表現します。ドキュメントのテキストコンテントは text
属性と tail
属性に格納されます (これが ElementTree と Document Object Model (DOM) との一番大きな違いです; DOM 内ではノードの数多くの型があります。 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
インスタンスを手にしてしまえば、あとはルートの Element
ノードを得るために getroot()
を呼び出せます。
文字列リテラルを受け取って (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 を削除する。 |
コメントと処理命令 (processing instruction=PI) も、 Element
ノードで表現されます。ノードがコメントあるいは処理命令であるかをチェックするにはこのようにします:
if elem.tag is ET.Comment:
...
elif elem.tag is ET.ProcessingInstruction:
...
XML 出力を生成するには ElementTree.write()
メソッドを呼び出す必要があります。 parse()
のように、文字列もしくはファイルのようなオブジェクトを渡せます:
# Encoding is US-ASCII
tree.write('output.xml')
# Encoding is UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')
(警告: 出力に使われるデフォルトエンコーディングは ASCII です。一般的な XML での作業では要素名に任意の Unicode 文字を含められるので、ASCII エンコーディングはあまり役に立ちません。要素名に 127 より大きなどんな文字が含まれても例外となりますので。ですから任意の Unicode 文字を扱うために UTF-8 のようなエンコーディングを指定するのが吉です。)
このセクションでは ElementTree インターフェイスのほんの一部しか記載していません。さらに詳しい情報については、パッケージの公式ドキュメントを参照して下さい。
参考
- http://effbot.org/zone/element-index.htm
- ElementTree の公式ドキュメント
hashlib パッケージ¶
Gregory P. Smith による新モジュール hashlib
が、 md5
と sha
モジュールを置き換えるものとして追加されました。 hashlib
は新たなセキュアハッシュ (SHA-224, SHA-256, SHA-384, SHA-512) サポートを追加しています。利用可能な場合、このモジュールは OpenSSL を使ってアルゴリズムのプラットフォームに最適化された高速実装を使います。
古い md5
と sha
モジュールは、後方互換のための hashlib へのラッパーとして残されています。新しいモジュールのインターフェイスは古いものと似てはいますが同じではありません。一番顕著な違いはそのコンストラクタ関数で、新しくハッシュオブジェクトを作るための名前が違います:
# Old versions
h = md5.md5()
h = md5.new()
# New version
h = hashlib.md5()
# Old versions
h = sha.sha()
h = sha.new()
# New version
h = hashlib.sha1()
# Hash that weren't previously available
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Alternative form
h = hashlib.new('md5') # Provide algorithm as a string
ハッシュオブジェクトを作ってしまえばあとはそのメソッドは以前と同じです: update(string)()
は指定された文字列を現在のダイジェスト状態にハッシュ更新し、 digest()
と hexdigest()
は結果のダイジェスト値をバイナリ文字列・16進数表記文字列として返し、 copy()
はダイジェスト状態を複製して新たなハッシュオブジェクトを作ります。
参考
hashlib
モジュールについてのドキュメント。
sqlite3 パッケージ¶
pysqlite モジュール (http://www.pysqlite.org) は SQLite 埋め込みデータベースへのラッパーであり、これが標準ライブラリに 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()
# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
# Insert a row of data
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
たいてい、SQL 操作は Python 変数の値を使う必要があります。この時、クエリーを Python の文字列操作を使って構築することは、安全とは言えないので、すべきではありません。そのようなことをするとプログラムが SQL インジェクション攻撃に対し脆弱になりかねません。
代わりに、DB-API のパラメータ割り当てを使います。 ?
を変数の値を使いたいところに埋めておきます。その上で、値のタプルをカーソルの execute()
メソッドの第2引数として引き渡します。(他のデータベースモジュールでは変数の場所を示すのに %s
や :1
などの異なった表記を用いることがあります。) 例を示します:
# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)
# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Larger example
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 文を実行した後データを取得する方法は3つありどれを使っても構いません。一つはカーソルをイテレータ (iterator) として扱う、一つはカーソルの fetchone()
メソッドを呼んで一致した内の一行を取得する、もう一つは fetchall()
メソッドを呼んで一致した全ての行のリストとして受け取る、という3つです。
以下の例ではイテレータの形を使います:
>>> 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)
>>>
For more information about the SQL dialect supported by SQLite, see https://www.sqlite.org.
参考
- http://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()
参考
- http://www.wsgi.org
- 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 にて開発されました。
Coverity, a company that markets a source code analysis tool called Prevent, provided the results of their examination of the Python source code. The analysis found about 60 bugs that were quickly fixed. Many of the bugs were refcounting problems, often occurring in error-handling code. See https://scan.coverity.com for the statistics.
PEP 353 に由来する C API の大きな変更がありました。これはインタプリタを
int
ではなくPy_ssize_t
型定義を使うように修正するものです。詳細は前のほうのセクション PEP 353: 添え字型に ssize_t を使う を参照して下さい。The design of the bytecode compiler has changed a great deal, no longer generating bytecode by traversing the parse tree. Instead the parse tree is converted to an abstract syntax tree (or AST), and it is the abstract syntax tree that’s traversed to produce the bytecode.
It’s possible for Python code to obtain AST objects by using the
compile()
built-in and specifying_ast.PyCF_ONLY_AST
as the value of the flags parameter: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]
No official documentation has been written for the AST code yet, but PEP 339 discusses the design. To start learning about the code, read the definition of the various AST nodes in
Parser/Python.asdl
. A Python script reads this file and generates a set of C structure definitions inInclude/Python-ast.h
. ThePyParser_ASTFromString()
andPyParser_ASTFromFile()
, defined inInclude/pythonrun.h
, take Python source as input and return the root of an AST representing the contents. This AST can then be turned into a code object byPyAST_Compile()
. For more information, read the source code, and then ask questions on python-dev.The AST code was developed under Jeremy Hylton’s management, and implemented by (in alphabetical order) Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo, and Neil Schemenauer, plus the participants in a number of AST sprints at conferences such as PyCon.
Evan Jones’s patch to obmalloc, first described in a talk at PyCon DC 2005, was applied. Python 2.4 allocated small objects in 256K-sized arenas, but never freed arenas. With this patch, Python will free arenas when they’re empty. The net effect is that on some platforms, when you allocate many objects, Python’s memory usage may actually drop when you delete them and the memory may be returned to the operating system. (Implemented by Evan Jones, and reworked by Tim Peters.)
Note that this change means extension modules must be more careful when allocating memory. Python’s API has many different functions for allocating memory that are grouped into families. For example,
PyMem_Malloc()
,PyMem_Realloc()
, andPyMem_Free()
are one family that allocates raw memory, whilePyObject_Malloc()
,PyObject_Realloc()
, andPyObject_Free()
are another family that’s supposed to be used for creating Python objects.Previously these different families all reduced to the platform’s
malloc()
andfree()
functions. This meant it didn’t matter if you got things wrong and allocated memory with thePyMem()
function but freed it with thePyObject()
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(type)
declares the function as returning a value of the specified type and uses a fast-calling qualifier.Py_LOCAL_INLINE(type)
does the same thing and also requests the function be inlined. IfPY_LOCAL_AGGRESSIVE()
is defined beforepython.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 であればその一つ上から、などです。 (Added by 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: an
--enable-universalsdk
switch was added to the configure script that compiles the interpreter as a universal binary able to run on both PowerPC and Intel processors. (Contributed by 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 キーワードパラメータも、もはや拒絶します。 - ライブラリ:
SimpleXMLRPCServer
クラスとDocXMLRPCServer
クラスに XML-RPC 操作を限られた URL パスに制限するrpc_paths
属性が追加されています; デフォルトでは'/'
と'/RPC2'
のみが許されています。rpc_paths
にNone
か空のタプルを渡すことで、このパスのチェックは無効になります。 - C API: 64 ビット機でより大きなデータを処理出来るよう、多くの関数が
int
の代わりにPy_ssize_t
を使うようになっています。拡張コードでは警告を避けて 64 ビット機サポートをするのに同じ変更が必要でしょう。この変更についての議論について書いた PEP 353: 添え字型に ssize_t を使う を参照して下さい。 - C API: obmalloc の変更により、
PyMem_*()
系関数とPyObject_*()
系関数を混ぜて使わないように注意しなければなりません。ある系列の*_Malloc()
でメモリを獲得するならば、解放は対応するほうの*_Free()
関数を使わなければいけません。
謝辞¶
The author would like to thank the following people for offering suggestions, corrections and assistance with various drafts of this article: 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.