0

私は、一般的なプログラミング言語のさまざまな実装を理解することを期待して、図(しゃれを意図したもの)を編集してきました。コードがコンパイルされるか解釈されるかは、コードの実装に依存し、プログラミング言語自体の側面ではないことを理解しています。

Pythonの解釈を直接コンパイル(C ++の例)と比較することに興味があります

ここに画像の説明を入力してください

および仮想マシンモデル(JavaまたはC#など)

ここに画像の説明を入力してください

上記の2つの図に照らして、.pyファイルを.pycに変換し、標準ライブラリ(モジュールと呼ばれるものを収集)を使用して実際に実行する方法の同様のフローチャートを作成するのを手伝っていただけませんか。SOの多くのプログラマーは、スクリプト言語としてのPythonはCPUではなくインタープリターによって実行されると指摘していますが、最終的にはハードウェアが計算を行う必要があるため、それはまったく不可能に聞こえます。

4

3 に答える 3

3

まず、これは実装の詳細です。私はCPythonとPyPyに精通しているので、それらに答えを制限しています。Jython、IronPython、およびその他の実装に対する回答は、おそらく根本的に異なります。

Pythonは「仮想マシンモデル」に近いです。Pythonコードは、知識レベルが高すぎる人々の発言とは対照的に、誰もが(私を含めて)カジュアルな議論で混乱させているにもかかわらず、解釈されることはありません。ロードされると、常にバイトコードにコンパイルされます(これもCPythonとPyPyで)。モジュールがインポートされ、.pyファイルからロードされたためにロードされた場合、コンパイル出力をキャッシュするために.pycファイルが作成される場合があります。この手順は必須ではありません。さまざまな方法でオフにすることができ、プログラムの実行は最も小さなビットには影響しません(ただし、モジュールをロードする次のプロセスで再度オフにする必要があります)。ただし、バイトコードへのコンパイルは避けられません。ディスクからロードされていない場合、バイトコードはメモリに生成されます。

このバイトコード(正確な詳細は実装の詳細であり、バージョンによって異なります)は、モジュールレベルで実行されます。これには、関数オブジェクトやクラスオブジェクトなどの構築が含まれます。これらのオブジェクトは、すでにメモリにあるバイトコードを再利用(ポインタを保持)するだけです。これは、コンパイル中/コンパイル後にコードとクラスが石で設定されるC++やJavaとは異なります。実行中に、importステートメントが検出される場合があります。輸入機械を説明するためのスペース、時間、理解が不足していますが、簡単な話は次のとおりです。

  • すでに一度インポートされている場合は、そのモジュールオブジェクトを取得します(静的言語がコンパイル時にのみ持つものの別のランタイム構造)。いくつかの組み込みモジュール(この質問の範囲を超えた理由で、すべてPyPyにあります)は、インタープリターのコアと非常に緊密に統合されており、非常に基本的であるという理由だけで、Pythonコードが実行される前にすでにインポートされています。sysそのようなモジュールです。一部のPythonコードは、特に対話型インタープリターを起動するときに、事前に実行される場合もあります(ルックアップsite.py)。
  • それ以外の場合、モジュールはにあります。このためのルールは私たちの関心事ではありません。最終的に、これらのルールはPythonファイルまたは動的にリンクされたマシンコードのいずれかに到達します(Windowsでは.DLL、Pythonモジュールは特に拡張子.pydを使用しますが、これは単なる名前です。UNIXでは同等の.soが使用されます)。
    • モジュールは最初にメモリにロードされます(動的にロードされるか、解析されてバイトコードにコンパイルされます)。
    • 次に、モジュールが初期化されます。拡張モジュールには、と呼ばれるもののための特別な機能があります。Pythonモジュールは、上から下に実行するだけです。正常に動作するモジュールでは、これはグローバルデータを設定し、関数とクラスを定義し、依存関係をインポートするだけです。もちろん、他のことも起こり得ます。結果のモジュールオブジェクトはキャッシュされ(ステップ1を思い出してください)、返されます。

これはすべて、標準ライブラリモジュールとサードパーティモジュールに適用されます。そのため、スクリプトにインポートする標準ライブラリモジュールのようにスクリプトを呼び出すと、紛らわしいエラーメッセージが表示される可能性があります(キャッシュが原因でクラッシュすることはありませんが、それ自体がインポートされます。

バイトコードの実行方法(質問の最後の部分)は異なります。CPythonは単にそれを解釈しますが、正しくご存知のように、それは魔法のようにCPUを使用しないという意味ではありません。代わりに、次に実行されるバイトコード命令を検出し、その命令のセマンティクスを実行するネイティブコードにジャンプする、大きな醜いループがあります。PyPyはもっと面白いです。それは解釈から始まりますが、途中でいくつかの統計を記録します。そうする価値があると判断すると、インタプリタが行うことの詳細な記録を開始し、高度に最適化されたネイティブコードを生成します。インタプリタは、Pythonコードの他の部分でも引き続き使用されます。多くのJVMとおそらく.NETでも同じですが、引用する図はそれを覆い隠していることに注意してください。

于 2012-06-29T19:42:18.553 に答える
1

Pythonのリファレンス実装の場合:

(.py)-> python(.pycをチェックします)->(.pyc)-> python(実行によりモジュールが動的にロードされます)

他の実装があります。最も注目すべきものは次のとおりです。

  • (.py)を(.class)にコンパイルし、そこからjavaパターンに従うjython
  • コンパイル時にJITを使用するpypy(.py)。そこからのチェーンは異なる可能性があります(pypyはcpython、jython、または.net環境で実行できます)
于 2012-06-29T18:58:57.513 に答える
0

Pythonは技術的にはスクリプト言語ですが、コンパイルもされます。Pythonソースはソースファイルから取得され、インタープリターに送られます。インタープリターは、ソースを内部でバイトコードにコンパイルしてから、外部または外部で破棄し、.pycのように保存します。

はい、Pythonは単一の仮想マシンであり、実際のハードウェアの上に配置されますが、すべてのpythonバイトコードは、実際のCPUのアセンブラーによく似たpvm(Python仮想マシン)の一連の命令です。

于 2012-06-29T18:58:31.663 に答える