Stackframe
Pythonは、inspectionが優れていて
関数,コード,スタックフレームのオブジェクトにまで
Pythonスクリプト上からアクセスできたりする。
import inspect def show_var(varname): """ 呼出元のローカル変数を表示 """ try: frame = inspect.currentframe() print "%s : %s" % (varname, frame.f_back.f_locals[varname]) finally: del frame if __name__ == "__main__": foo = "HiNa" show_var("foo") # foo : HiNa
エラーや例外時にでるメッセージは、このframeオブジェクトの情報を参照している。
これを使うと、Perlの caller みたいな関数も定義できる。
def caller(num=1): """ 引数は、幾つ前のスタックを辿るかを整数で指定。初期値は1。 [ 呼出元の名前, 呼出元のファイル, 呼出元の行番号 ] """ assert num > 0, "Stack depth number must be greater than zero." try: frame = inspect.currentframe() for _ in xrange(num-1): frame = frame.f_back code = frame.f_code return [ code.co_name, code.co_filename, frame.f_lineno ] finally: del frame
Python in parrotで心配になったのは、先にも書いたけど
この code や frame オブジェクトの互換性をどう解決するのか。
いずれも C で実装されていて、Pythonプログラムの実行に深く関わっている。
例えば、関数の引数のフォーマット情報を表示するinspectの関数などは、
関数オブジェクト内のコード・オブジェクトが持つバイトコードの情報を参照している。
当然ながら python bytecode -> parrot bytecodeになると、バイトコードが代わるので、
この部分の変更は避けられない。
また、parrot用に書き直されるとした場合でも、
branchになるので、CPythonとParrotPython版両方の保守が発生する。
開発者でもないのに余計な心配かなとは思うが、実装依存部分を取り除くには手間がかかりそうだ。