Python 2.6以降で作ったコードを 2.5へ対応するときに引っかかる点
python-specfor · PyPI を作るとき、Python2.6と3.1を中心に書いてました。
これを2.5にも対応させたのですが、そのときその差が意外と大きかったのが新鮮だったのでメモ。
with文
2.5では、with文を有効にするには、そのファイルで__future__指定する必要があります。
from __future__ import with_statement
これは今回の中で一番分かりやすかった違いですが、specfor自体がwith文を使わせるものであるため、そこそこ多くのファイルに埋めこむことになりました。
namedtuple
collections.namedtupleも2.6からの機能です。
自らはnamedtuple型を定義しなかったのですが、標準モジュールのほうで結構使っていて、それに依存したコードがありました。
対策A: 代入時tuple展開
# difflib.SequenceMatcher.get_matching_blocks()の戻り値 macthesにて for match in matches: vindex = match.a + match.size
を以下のようにする
# difflib.SequenceMatcher.get_matching_blocks()の戻り値 macthesにて for a, b, size in matches: vindex = a + size
対策B: classを作る
matchはループ中でのみ使うものだったので、展開するのが楽です。
しかし、tupleを持ち運んで使っている場合もあって、その場合には、同じインタフェースを持ったclassを作成しました。
class funcspec(object): def __init__(self, argspec): self.args, self.varargs, self.keywords, self.defaults = argspec pass pass def getargspec(func): import inspect return funcspec(inspect.getargspec(func))
argspecがnamedtupleですが、それをfuncspecクラスで同じ名前のメンバーとなるよう調整しています。
相対import
python2.5は2.6以降にくらべ、相対importの能力が低いです。
from .framework import * # 2.5ではここで*は使えない。
# 2.5の場合、__main__モジュールでは、-mオプション経由の起動でも、相対importが使えない from . import version def main(): ... if __name__ == "__main__": main()
これは、以下のように対策しました
from .framework import spec # 個別の名前で指定する
# main内で、絶対importを使う def main(): from specfor import version ... if __name__ == "__main__": main()