はじめに
本記事では、Pythonコードの実行フローを追いながら、インタプリタ・ランタイム・OS・実行環境といった概念がそれぞれどのように関与しているか、学んだことをまとめようと思います。
Pythonコードの実行フローを追う
今回登場する言葉
インタプリタ型言語の実行フローを説明する際に出てくる言葉について、簡単にまとめます。
用語 | 説明 |
---|---|
ソースコード | 開発者が記述したプログラムファイル(例:.py , .js , .c など)。 |
インタプリタ | ソースコードを1行ずつ読み取り・実行するプログラム(例:CPython、Node.jsなど)。 |
コンパイラ | ソースコードを一括で機械語または中間コードに変換するプログラム。 |
中間コード | バイトコードなど仮想マシンで動く中間形式のコード。JavaやPythonで使われる。 |
仮想マシン(VM) | 中間コードを実行する仮想的なコンピュータ(例:JVM, .NET CLR) |
ランタイム環境 | 実行時にPythonが動作する際に内部で使う仕組み(標準ライブラリ、例外処理、GCなど) |
実行環境 | 実行に必要な前提条件(OS、依存パッケージ、設定など) |
OS | アプリケーションとハードウェアの橋渡しをする基盤ソフトウェア(例:Linux, Windows) |
実行時のステップ
では次に、Pythonコードを実際に書き、その出力を確認するまでにどのような処理が内部で行われているのか、実行フローを一つずつ見ていきます。
ここでは単純なコードを例にとって、裏側で行われている処理を段階的に説明します。
-
ソースコードの作成
.py ファイルに Python のコードを記述します。# hello.py print("Hello, world!")
-
インタプリタの起動
コマンドラインなどから以下のように実行します。python3 hello.py
この時点でCPython(標準的な Python 処理系)が起動します。
-
バイトコードへの変換
ソースコードは CPython によって .pyc という形式のバイトコードに変換されます。
これはPython内部で使われる中間形式で、実行効率を高めるために使われます。
生成されたバイトコードはメモリ上に保持されるか、次回以降の起動を高速化するために pycache に保存される。 -
PVM(Python Virtual Machine)による実行
生成されたバイトコードは PVM(Python仮想マシン)によって1命令ずつ実行されます。
PVM が 1 命令ずつバイトコードを解釈し、対応する処理をランタイム上で実行します。 -
ランタイム環境による依存解決
PVMが CALL_FUNCTION print を解釈すると、print 関数の定義にアクセスする必要があります。
ランタイム環境(標準ライブラリやインストール済みパッケージ)から、print の実装をロードします。
もし import 文があれば、同様にそのモジュールをランタイム環境から読み込みます。 -
OSによる最終処理
print() の本体では、Python の組み込み I/O 関数を通じて システムコール を行い、OS に「標準出力(stdout)へ文字列を送信せよ」と依頼します。
OS(Linux/Mac/Windows など)はこの依頼を受け、端末やコンソールに文字列を表示します。 -
プログラム終了
バイトコードの命令がすべて実行されると PVM は終了し、CPython インタプリタもプロセスを終了します。
OS はプロセス終了を確認し、リソース(メモリ、ファイルハンドルなど)を解放します。
上記のPythonコード実行のフローを簡単にまとめると、
- ソースコード作成 → .py ファイルに Python 文法で記述
- CPython 起動 → コマンド python hello.py
- バイトコード生成 → 中間命令に変換
- PVM による命令実行 → Python の処理ロジックを逐次実行
- ランタイム環境 から関数・モジュールをロード
- システムコール を通じて OS に画面表示などを依頼
- プロセス終了 → リソース解放
こんな感じになります。
まとめ
Pythonの実行フローを通じて、インタプリタ型言語がどのようにソースコードを実行へとつなげているかの一端を学びました。今後は、コンパイラ型言語との違いや、それぞれのメリット・用途の違いについても理解を深めていこうと思います。