4. 実行モデル
*************


4.1. プログラムの構造
=====================

Python プログラムはコードブロックから構成されます。 ブロック (*block*)
は、一つのまとまりとして実行される Python プログラムテキストの断片です
。 モジュール、関数本体、そしてクラス定義はブロックであり、対話的に入
力された個々のコマンドもブロックです。 スクリプトファイル (インタープ
リタに標準入力として与えられたり、インタープリタにコマンドライン引数と
して与えられたファイル) もコードブロックです。 スクリプトコマンド (イ
ンタープリタのコマンドライン上で "-c" オプションで指定されたコマンド)
もコードブロックです。 引数 "-m" を使用して、コマンドラインからトップ
レベルスクリプト(すなわちモジュール "__main__" )として実行されるモジュ
ールもまたコードブロックです。組み込み関数 "eval()" や "exec()" に渡さ
れた文字列引数もコードブロックです。

コードブロックは、実行フレーム (*execution frame*) 上で実行されます。
実行フレームには、 (デバッグに使われる) 管理情報が収められています。ま
た、現在のコードブロックの実行が完了した際に、どのようにプログラムの実
行を継続するかを決定しています。


4.2. 名前づけと束縛 (naming and binding)
========================================


4.2.1. 名前の束縛
-----------------

*名前 (name)* は、オブジェクトを参照します。名前を導入するには、名前へ
の束縛 (name binding) 操作を行います。

以下の構文が名前を束縛します:

* 関数の仮引数。

* クラス定義,

* 関数定義,

* 代入式,

* 代入先 が識別子で、次の代入が行われる箇所にある場合。

  * "for" ループのヘッダー。

  * "with" 文、"except" 節、"except*" 節の "as" の後、または構造的パタ
    ーンマッチングの as パターン内。

  * 構造的パターンマッチングのキャプチャパターン内。

* "import" 文.

* "type" 文。

* 型パラメータのリスト。

The "import" statement of the form "from ... import *" binds all names
defined in the imported module, except those beginning with an
underscore. This form may only be used at the module level.

"del" 文で指定される対象は、("del" の意味付けは、実際は名前の解放
(unbind) ですが) 文の目的上、束縛済みのものとみなされます。

代入文や import 文はいずれも、クラスや関数定義、モジュールレベル (トッ
プレベルのコードブロック) 内で起こります。

名前がブロック内で束縛される場合、"nonlocal" または "global" で宣言さ
れていなければ、そのブロックのローカル変数です。 名前がモジュールレベ
ルで束縛される場合はグローバル変数です (モジュールのコードブロックの変
数は、ローカル変数であると同時にグローバル変数でもあります)。 コードブ
ロック内で使われていても、そこで定義されていない変数は *自由変数* です
。

プログラムのテキスト中に現れる各名前は、以下の名前解決規則によって定ま
る、その名前の *束縛 (binding)* を参照します。


4.2.2. 名前解決
---------------

スコープ (*scope*) は、ブロック内の名前の可視性を決めます。 ローカル変
数があるブロック内で定義されている場合、変数のスコープはそのブロックを
含みます。 関数ブロック内で名前の定義を行った場合、その中のブロックが
名前に別の束縛を行わない限り、定義ブロック内の全てのブロックを含むよう
にスコープが拡張されます。

ある名前がコードブロック内で使われると、その名前を最も近傍から囲うよう
なスコープ (最内スコープ: nearest enclosing scope) を使って束縛の解決
を行います。こうしたスコープからなる、あるコードブロック内で参照できる
スコープ全ての集合は、ブロックの環境(*environment*)と呼ばれます。

名前が全く見付からなかったときは、 "NameError" 例外が送出されます。 現
在のスコープが関数のもので、名前が使われる場所でローカル変数がまだ値に
束縛されていない場合、 "UnboundLocalError" 例外が送出されます。
"UnboundLocalError" は "NameError" の子クラスです。

コードブロック内のどこかに名前の束縛操作があると、そのブロック内でのそ
の名前の使用はすべて、現在のブロックへの参照として扱われます。 そのた
め、束縛する前にその名前をブロック内で使うと、エラーにつながる場合があ
ります。 この規則は分かりにくい点に注意が必要です。 Python では変数の
宣言は不要で、コードブロック内のどこでも名前を束縛できます。 ブロック
のテキスト全体から名前の束縛操作を探すことで、そのブロックのローカル変
数を判断できます。 例は UnboundLocalError についての FAQ 項目 を参照し
てください。

If the "global" statement occurs within a block, all uses of the names
specified in the statement refer to the bindings of those names in the
top-level namespace.  Names are resolved in the top-level namespace by
searching the global namespace, i.e. the namespace of the module
containing the code block, and the builtins namespace, the namespace
of the module "builtins".  The global namespace is searched first.  If
the names are not found there, the builtins namespace is searched
next. If the names are also not found in the builtins namespace, new
variables are created in the global namespace. The global statement
must precede all uses of the listed names.

"global" 文は、同じブロックの束縛操作と同じスコープを持ちます。ある自
由変数の最内スコープに global 文がある場合、その自由変数はグローバル変
数とみなされます。

"nonlocal" 文は、指定された名前が、最も近い外側の関数スコープで以前に
束縛された変数を参照するようにします。 外側のどの関数スコープにもその
名前がなければ、コンパイル時に "SyntaxError" を送出します。 型パラメー
タ は "nonlocal" 文で再束縛できません。

あるモジュールの名前空間は、そのモジュールが最初に import された時に自
動的に作成されます。スクリプトの主モジュール (main module) は常に
"__main__" と呼ばれます。

クラス定義のブロックと、"exec()" や "eval()" に渡す引数では、名前解決
に特別な規則があります。 クラス定義は実行可能な文で、名前を使ったり定
義したりできます。 これらの参照は通常の名前解決規則に従いますが、束縛
されていないローカル変数をグローバル名前空間で探す点は例外です。 クラ
ス定義の名前空間は、クラスの属性辞書になります。 クラスブロックで定義
した名前のスコープはそのブロックに限られ、メソッドのコードブロックには
及びません。 内包表記やジェネレータ式も同様ですが、アノテーションスコ
ープ は例外で、外側のクラススコープにアクセスできます。 このため、次の
コードは失敗します。

   class A:
       a = 42
       b = list(a + i for i in range(10))

一方、次のコードは成功します。

   class A:
       type Alias = Nested
       class Nested: pass

   print(A.Alias.__value__)  # <type 'A.Nested'>


4.2.3. アノテーションスコープ
-----------------------------

*アノテーション*、型パラメータのリスト、"type" 文は *アノテーションス
コープ* を導入します。 その動作はおおむね関数スコープと同じですが、後
述する例外があります。

アノテーションスコープは次の文脈で使われます。

* *関数アノテーション*。

* *変数アノテーション*。

* ジェネリック型エイリアス の型パラメータのリスト。

* ジェネリック関数 の型パラメータのリスト。 ジェネリック関数のアノテー
  ションはアノテーションスコープ内で実行されますが、デフォルト値やデコ
  レータはその外で実行されます。

* ジェネリッククラス の型パラメータのリスト。 ジェネリッククラスの基底
  クラスとキーワード引数はアノテーションスコープ内で実行されますが、デ
  コレータはその外で実行されます。

* 型パラメータの上限、制約、デフォルト値 (遅延評価)。

* 型エイリアスの値 (遅延評価)。

アノテーションスコープは、次の点で関数スコープと異なります。

* アノテーションスコープは、外側のクラスの名前空間にアクセスできます。
  クラススコープの直下、またはクラススコープの直下にある別のアノテーシ
  ョンスコープ内にアノテーションスコープがある場合、その中のコードは、
  クラス本体で直接実行する場合と同様にクラススコープで定義された名前を
  使えます。 これは、クラス内で定義された通常の関数が、クラススコープ
  で定義された名前にアクセスできないこととは対照的です。

* アノテーションスコープ内の式には、"yield"、"yield from"、"await"、
  ":=" の式を含められません (アノテーションスコープ内にある別のスコー
  プでは使えます)。

* アノテーションスコープで定義された名前は、内側のスコープの
  "nonlocal" 文では再束縛できません。 アノテーションスコープ内に現れ得
  る構文要素のうち、新しい名前を導入できるのは型パラメータだけなので、
  この制限の対象も型パラメータだけです。

* アノテーションスコープには内部的な名前がありますが、その名前はスコー
  プ内で定義したオブジェクトの *修飾名* には反映されません。 オブジェ
  クトの "__qualname__" は、その外側のスコープで定義した場合と同じにな
  ります。

Added in version 3.12: **PEP 695** の一部として、Python 3.12 でアノテ
ーションスコープを導入しました。

バージョン 3.13 で変更: **PEP 696** で導入された型パラメータのデフォル
ト値にも、アノテーションスコープを使うようになりました。

バージョン 3.14 で変更: **PEP 649** と **PEP 749** の規定に従い、アノ
テーションにもアノテーションスコープを使うようになりました。


4.2.4. 遅延評価
---------------

ほとんどのアノテーションスコープは *遅延評価* されます。 これにはアノ
テーション、"type" 文で作成した型エイリアスの値、型パラメータの構文 で
作成した型変数の上限、制約、デフォルト値が含まれます。 つまり、型エイ
リアスや型変数、またはアノテーションを持つオブジェクトを作成した時点で
は評価されません。 型エイリアスの "__value__" 属性にアクセスしたときな
ど、必要になった時点で初めて評価されます。

例:

   >>> type Alias = 1/0
   >>> Alias.__value__
   Traceback (most recent call last):
     ...
   ZeroDivisionError: division by zero
   >>> def func[T: 1/0](): pass
   >>> T = func.__type_params__[0]
   >>> T.__bound__
   Traceback (most recent call last):
     ...
   ZeroDivisionError: division by zero

この例では、型エイリアスの "__value__" 属性または型変数の "__bound__"
属性にアクセスした時点で初めて例外を送出します。

この動作は主に、型エイリアスや型変数の作成時点ではまだ定義されていない
型を参照する場合に役立ちます。 例えば、遅延評価によって相互に再帰する
型エイリアスを作成できます。

   from typing import Literal

   type SimpleExpr = int | Parenthesized
   type Parenthesized = tuple[Literal["("], Expr, Literal[")"]]
   type Expr = SimpleExpr | tuple[SimpleExpr, Literal["+", "-"], Expr]

遅延評価される値は アノテーションスコープ 内で評価されます。 そのため
、その値の中に現れる名前は、直近の外側のスコープで使われた場合と同じよ
うに検索されます。

Added in version 3.12.


4.2.5. 組み込みと制限付きの実行
-------------------------------

ユーザは "__builtins__" に触れるべきではありません; これは厳密に実装の
詳細です。組み込みの名前空間の中の値をオーバーライドしたいユーザは、
"builtins" モジュールを "import" して、その属性を適切に変更するべきで
す。

あるコードブロックの実行に関連する組み込み名前空間は、実際にはコードブ
ロックのグローバル名前空間から名前 "__builtins__" を検索することで見つ
かります; "__builtins__"  は辞書かモジュールでなければなりません (後者
の場合はモジュールの辞書が使われます)。デフォルトでは、 "__main__" モ
ジュール中においては、 "__builtins__" は組み込みモジュール "builtins"
です; それ以外の任意のモジュールにおいては、 "__builtins__" は
"builtins" モジュール自身の辞書のエイリアスです。


4.2.6. 動的な機能とのやりとり
-----------------------------

自由変数の名前解決はコンパイル時でなく実行時に行われます。つまり、以下
のコードは42を出力します:

   i = 10
   def f():
       print(i)
   i = 42
   f()

"eval()" と "exec()" 関数は、名前の解決に、現在の環境の全てを使えるわ
けではありません。名前は呼び出し側のローカルやグローバル名前空間で解決
できます。自由変数は最内名前空間ではなく、グローバル名前空間から解決さ
れます。 [1] "exec()" と "eval()" 関数にはオプションの引数があり、グロ
ーバルとローカル名前空間をオーバライドできます。名前空間が一つしか指定
されなければ、両方の名前空間として使われます。


4.3. 例外
=========

例外とは、コードブロックの通常の制御フローを中断して、エラーやその他の
例外的な状況を処理できるようにするための手段です。例外はエラーが検出さ
れた時点で *送出 (raise)* されます; 例外は、エラーが発生部の周辺のコー
ドブロックか、エラーが発生したコードブロック直接または間接的に呼び出し
ているコードブロックで *処理 (handle)* することができます。

Python インタプリタは、ランタイムエラー (ゼロ除算など) が検出されると
例外を送出します。Python プログラムから、 "raise" 文を使って明示的に例
外を送出することもできます。例外ハンドラ (exception handler) は、
"try" ... "except" 文で指定することができます。 "try" 文の "finally"
節を使うとクリーンアップコード (cleanup code) を指定できます。このコー
ドは例外は処理しませんが、先行するコードブロックで例外が起きても起きな
くても実行されます。

Python のエラー処理は「終了 (termination)」モデルを採用しています。 例
外ハンドラは、何が起きたかを調べ、外側のレベルで実行を続けられます。
しかし、エラーの原因を修復して失敗した操作を再試行することはできません
(問題のあるコード部分に先頭から入り直す場合を除きます)。

例外が全く処理されないとき、インタプリタはプログラムの実行を終了させる
か、対話メインループに処理を戻します。 どちらの場合も、例外が
"SystemExit" でなければ、スタックのトレースバックを出力します。

例外は、クラスインスタンスによって識別されます。 "except" 節はインスタ
ンスのクラスにもとづいて選択されます: これはインスタンスのクラスか、そ
の *非仮想基底クラス* を参照します。このインスタンスはハンドラによって
受け取られ、例外条件に関する追加情報を伝えることができます。

注釈:

  例外のメッセージは、Python API 仕様には含まれていません。メッセージ
  の内容は、ある Python のバージョンと次のバージョンの間で警告なしに変
  更される可能性があるので、複数バージョンのインタプリタで動作するよう
  なコードは、例外メッセージの内容に依存させるべきではありません。

"try" 文については、 try 文 節、 "raise" 文については raise 文 節も参
照してください。


4.4. 実行時の構成要素
=====================


4.4.1. 一般的な計算モデル
-------------------------

Python の実行モデルは、外部から切り離されて動作するものではありません
。 ホストマシン上で、OS があればそれも含む、ホストの実行環境を通じて動
作します。 プログラムを実行するとき、ホスト上での実行を概念的な層に分
けると次のようになります。

      **ホストマシン**
         **プロセス** (グローバルなリソース)
            **スレッド** (機械語コードを実行)

各プロセスは、ホスト上で実行されるプログラムを表します。 プロセス自体
をプログラムのデータの部分、プロセスのスレッドを実行の部分と考えてくだ
さい。 この区別は、Python ランタイムの概念を理解するうえで重要になりま
す。

データの部分であるプロセスは、プログラムが動作する実行コンテキストです
。 その大部分は、メモリ、シグナル、ファイルハンドル、ソケット、環境変
数など、ホストがプログラムに割り当てたリソースの集合で構成されます。

プロセス同士は隔離され、互いに独立しています (ホスト同士も同様です)。
ホストはプロセス間の調整を行うとともに、各プロセスに割り当てたリソース
へのアクセスを管理します。

各スレッドは、プログラムのプロセスに割り当てられたリソースを使い、プロ
グラムの機械語コードを実際に実行する部分を表します。 どのように、いつ
実行するかは、全面的にホストに委ねられます。

Python から見た場合、プログラムは常にちょうど一つのスレッドで開始しま
す。 ただし、その後に増えて、複数のスレッドが同時に動作することもあり
ます。 一つのプロセスで複数のスレッドを使うことをサポートしないホスト
もありますが、ほとんどのホストはサポートしています。 プロセスとは異な
り、同じプロセスのスレッド同士は隔離されておらず、独立してもいません。
具体的には、一つのプロセスのすべてのスレッドが、そのプロセスのすべての
リソースを共有します。

スレッドの基本的な特徴は、それぞれが独立して、ほかのスレッドと同時に *
動作する* ことです。 同時というのは、概念上だけの場合 (「並行」) も、
物理的に同時の場合 (「並列」) もあります。 いずれの場合も、スレッドは
実質的に、互いに同期しない速さで動作します。

注釈:

  動作の速さが同期していないため、あるスレッドで実行されるコードから見
  て、プロセスのどのメモリについても一貫性が維持される保証はありません
  。 そのため、マルチスレッドのプログラムでは、意図的に共有するリソー
  スへのアクセスを注意深く調整する必要があります。 同様に、*それ以外*
  のリソースには複数のスレッドからアクセスしないよう、徹底して注意する
  必要があります。 そうしないと、同時に動作する二つのスレッドが、共有
  データの利用を意図せず妨げ合う可能性があります。 これは Python プロ
  グラムにも Python ランタイムにも当てはまります。この広範で構造化され
  ていない要件に対応する負担は、スレッドが提供する直接的な並行実行機能
  の代償です。 必要な規律を守らなければ、一般に、非決定的なバグやデー
  タ破損に対処することになります。


4.4.2. Python ランタイムのモデル
--------------------------------

Python プログラムにも同じ概念的な層が当てはまりますが、Python 固有のデ
ータの層がいくつか加わります。

      **ホストマシン**
         **プロセス** (グローバルなリソース)
            Python のグローバルランタイム (*状態*)
               Python インタープリタ (*状態*)
                  **スレッド** (Python バイトコードと「C-API」を実行)
                     Python のスレッド *状態*

概念的には、Python プログラムの開始時点では、図にある各要素が一つずつ
存在します。 ランタイムには複数のインタープリタが追加されることがあり
、各インタープリタにも複数のスレッド状態が追加されることがあります。

注釈:

  Python の実装が、ランタイムの各層を必ずしも別々に、あるいは具体的な
  形で実装するとは限りません。 例外は、"threading" モジュールのように
  、層の区別を直接規定したり利用者に公開したりしている箇所だけです。

注釈:

  最初のインタープリタは、通常「メイン」インタープリタと呼ばれます。
  CPython などの一部の Python 実装では、メインインタープリタに特別な役
  割を割り当てています。同様に、ランタイムを初期化したホストのスレッド
  は「メイン」スレッドと呼ばれます。 プロセスの最初のスレッドと同じこ
  とが多いものの、異なる場合もあります。 「メインスレッド」が、さらに
  限定して最初のスレッド状態を指す場合もあります。 Python ランタイムは
  、シグナルの処理など、特定の役割をメインスレッドに割り当てることがあ
  ります。

Python ランタイム全体は、グローバルランタイム状態、インタープリタ、ス
レッド状態で構成されます。 ランタイムは、特に複数のホストスレッドから
使われる場合も含め、存続期間を通じてこれらすべての状態の一貫性を維持し
ます。

概念的には、グローバルランタイムは単なるインタープリタの集合です。 各
インタープリタは基本的には隔離されて互いに独立していますが、一部のデー
タやその他のリソースを共有する場合があります。 ランタイムには、こうし
たグローバルなリソースを安全に管理する責任があります。 リソースの実際
の性質や管理方法は実装に依存します。 結局、グローバルランタイムが外部
に提供する機能は、インタープリタの管理に限られます。

一方、「インタープリタ」は、概念的には通常私たちが完全な機能を備えた「
Python ランタイム」と考えるものに相当します。 ホストのスレッドで実行さ
れる機械語コードが Python ランタイムとやりとりするときは、特定のインタ
ープリタのコンテキストで Python を呼び出します。

注釈:

  ここでいう「インタープリタ」は、通常スレッド内でコンパイル済みの
  Python コードを実行する「バイトコードインタープリタ」とは異なります
  。本来は、現在「インタープリタ」と呼んでいるものを「Python ランタイ
  ム」と呼ぶのが適切でしょう。 しかし、少なくとも 1997 年に導入されて
  以来、「インタープリタ」と呼ばれています (CPython:a027efa5b)。

各インタープリタは、Python ランタイムの動作に必要な状態のうち、プロセ
ス全体で共有されず、スレッド固有でもないものをすべて完全にカプセル化し
ます。 特に、インタープリタの状態は、一度使った後も次に使うまで保持さ
れます。 これには "sys.modules" などの基本的なデータが含まれます。 ラ
ンタイムは、同じインタープリタを使う複数のスレッドが、それを安全に共有
できるようにします。

Python の実装は、一つのプロセス内で複数のインタープリタを同時に使うこ
とをサポートする場合があります。 各インタープリタは互いに独立し、隔離
されています。 例えば、それぞれが固有の "sys.modules" を持ちます。

スレッド固有のランタイム状態については、グローバルランタイムがインター
プリタの集合を持つのと同様に、各インタープリタがスレッド状態の集合を持
ち、管理します。 必要な数のホストスレッドに対応するスレッド状態を持つ
ことができます。 あまり一般的ではありませんが、一つのホストスレッドに
対して複数のスレッド状態を持つことさえあります。

概念的には、各スレッド状態には、一つのホストスレッド内でインタープリタ
が動作するために必要な、スレッド固有のランタイムデータがすべて含まれま
す。 これには現在送出されている例外と、スレッドの Python 呼び出しスタ
ックが含まれます。 ほかのスレッド固有のリソースを含む場合もあります。

注釈:

  「Python スレッド」という用語はスレッド状態を指す場合もありますが、
  通常は "threading" モジュールで作成したスレッドを意味します。

各スレッド状態は、その存続期間を通じて、常にちょうど一つのインタープリ
タと、ちょうど一つのホストスレッドに結び付けられています。 そのスレッ
ド内で、そのインタープリタとともに使われることしかありません。

一つのホストスレッドに複数のスレッド状態が結び付けられる場合があります
。 それらが属するインタープリタは、異なることも同じこともあります。 た
だし、一つのホストスレッドが一度に使えるのは、そのスレッドに結び付けら
れたスレッド状態のうち一つだけです。

スレッド状態同士は隔離され、互いに独立しており、データを共有しません。
ただし、インタープリタや、そのインタープリタに属するオブジェクトなどの
リソースを共有する場合はあります。

プログラムの実行中には、"threading" モジュールで新しい Python スレッド
を作成できます (スレッドをサポートするプラットフォームと Python 実装の
場合)。 "os"、"subprocess"、"multiprocessing" モジュールでは追加のプロ
セスを作成できます。 "interpreters" モジュールではインタープリタを作成
して使えます。 各インタープリタでは、"asyncio" を使ってコルーチン
(async) を実行できます。 通常は一つのスレッド (多くの場合メインスレッ
ド) 内で実行します。

-[ 脚注 ]-

[1] この制限は、上記の操作によって実行されるコードが、モジュールをコン
    パイルしたときには利用できないために起こります。
