明けましておめでとうございます。新年にあたり、私は今年の目標を立てました。 それはCPythonのソースコードを読むことです。ソースコードはgithubで公開されています。

バージョンはPython 3.9.1です。読みはじめた時の最新版で、 この版を選んだことにそれ以上の深い意味はありません。 大量のソースコードを読むには、良い道具が必要です。ソースの中で関数が呼ばれていたら、 すぐにその定義のところにジャンプしたり、また戻ってこれるような機能は不可欠です。 筆者はCLionを使うことにしました。有償のツールなので少し迷いましたが日頃からPythonの開発には PyCharmを使っているので、キーバインドがほぼ同じなことが決め手になりました。

まずはトップディレクトリにあるREADMEを読みます。最初にビルドの仕方が書いてあります。 一般的なオープンソースプロジェクトのお作法どおりです。

./configure
make
make test
sudo make install

テストを実行すると、いくつかエラーがでましたが、 とりあえず動くバイナリは出来上がったようなので気にせず進みます。 まだ怖いのでinstallはしないでおきます。

最初にすることはディレクトリ構成を理解することと、 処理がスタートするエントリーポイントを見つけることです。 デバッガの下で、ビルドでルートディレクトリに出来上がった python.exe (筆者の環境はMacです)を対話モードで実行してみます。 プロンプトが表示され、標準入力からの入力待ちになりました。 ここでデバッガで割り込みをかけてみます。 スタックのトレースをみれば、どこから実行が始まっているのかわかります。 main

Programs/python.c

の中にあることがわかりました。理屈から言えば、ここから全ての制御が スタートするので丹念にソースを追っていけば全てのPythonの挙動が解明 できるはずです。とはいえ、実際は気が遠くなりそう作業なのですがね。

Modules/main.c
Python/pythonrun.c

といったファイルへ次々と制御が渡ります。Pythonを対話モード立ち上げると、 プロンプトを表示した後、標準入力から入力を受けとり、 その内容を評価して、結果を印字するというループ ( REPL; read evaluate print loop)を繰り返すのですが、 そのループは以下の部分であることがわかりました。

PyRun_InteractiveLoopFlags(FILE *fp,
    const char *filename_str,
    PyCompilerFlags *flags)

この先は、入力されたソースコードが字句解析、構文解析され抽象構文木 へと変換され、その後コンパイル、実行という流れになります。 今回はここまで、続きは次回以降のお楽しみです。 冒険の旅は始まったばかりです。

[参考文献]

Python Developer’s Guide

野中 哲

野中 哲

エンジニア、開発担当

2016年3月に入社。NECで衛星通信の制御用ソフト開発、アップルでMacOSのローカリゼーション、AppleShareファイルサーバの開発等に従事。プライベートではRuby,Haskellなどのプログラミングとラグビー観戦を好む。最近の興味はSwiftでiOSアプリを開発すること。FAA自家用パイロットライセンス所有。