Pythonはインタプリタ言語であることを理解するように言われました...
しかし、Pythonソースコードを見る.pyc
と、Windowsが「コンパイル済みPythonファイル」として識別するファイルが表示されます。
これらはどこから来るのですか?
Pythonはインタプリタ言語であることを理解するように言われました...
しかし、Pythonソースコードを見る.pyc
と、Windowsが「コンパイル済みPythonファイル」として識別するファイルが表示されます。
これらはどこから来るのですか?
Pythonはインタプリタ言語であることを理解するように言われました...
この人気のあるミームは正しくないか、むしろ(自然)言語レベルの誤解に基づいて構築されています。同様の間違いは、「聖書はハードカバーの本です」と言うことです。その直喩を説明させてください...
「聖書」は、本のクラスであるという意味での「本」です。「聖書の写し」として特定された本は、基本的な共通点があるはずです(内容は、異なる言語でも、許容できる翻訳、脚注のレベル、その他の注釈が異なる場合もあります)。ただし、これらの本は基本とは見なされない無数の側面で完全に異なることが許されています-バインディングの種類、バインディングの色、印刷に使用されるフォント、イラスト(ある場合)、書き込み可能なマージンが広いかどうか、組み込みのブックマークの数と種類、などなど。
聖書の典型的な印刷が実際にハードカバーの装丁になっている可能性は十分にあります-結局のところ、それは通常、何度も何度も読んだり、いくつかの場所でブックマークしたり、特定の章と節のポインターを探して親指を立てたりすることを意図した本です、などなど、および優れたハードカバーのバインディングは、そのような使用の下で特定のコピーを長持ちさせることができます。ただし、これらはありふれた(実用的な)問題であり、特定の実際の本のオブジェクトが聖書のコピーであるかどうかを判断するために使用することはできません。ペーパーバック印刷は完全に可能です。
同様に、Pythonは、言語実装のクラスを定義するという意味で「言語」であり、いくつかの基本的な点ですべて類似している必要があります(構文、明示的に異なることが許可されている部分を除くほとんどのセマンティクス)が、完全に許可されています与えられたソースファイルをどのように処理するか、ソースをいくつかの下位レベルの形式にコンパイルするかどうか(もしそうなら、どの形式にするか)、そしてそのようなものを保存するかどうかなど、ほぼすべての「実装」の詳細が異なります。コンパイルされたフォーム、ディスクなど)、フォームの実行方法など。
従来の実装であるCPythonは、略して単に「Python」と呼ばれることがよくありますが、MicrosoftのIronPython(CLRコード、つまり「.NET」にコンパイルされる)、Jythonと並んで、いくつかの本番品質の実装の1つにすぎません。 (JVMコードにコンパイルされます)、PyPy(Python自体で記述され、「ジャストインタイム」で生成されたマシン言語を含む多種多様な「バックエンド」形式にコンパイルできます)。多くの表面的に異なる本のオブジェクトがすべて聖書(== "聖書のコピー")であるのと同じように、それらはすべてPython(== "Python言語の実装")です。
特にCPythonに関心がある場合は、ソースファイルをPython固有の下位レベル形式(「バイトコード」と呼ばれる)にコンパイルし、必要に応じて自動的にコンパイルします(ソースファイルに対応するバイトコードファイルがない場合、またはバイトコードファイルはソースよりも古いか、別のPythonバージョンでコンパイルされています)。通常、バイトコードファイルはディスクに保存されます(将来の再コンパイルを回避するため)。OTOH IronPythonは通常、CLRコード(ディスクに保存するかどうかに応じて)とJythonからJVMコード(ディスクに保存するかどうかに応じて)にコンパイルし.class
ます。保存する場合は拡張機能を使用します。
これらの下位レベルのフォームは、「インタープリター」とも呼ばれる適切な「仮想マシン」(CPython VM、.Netランタイム、Java VM(別名JVM))によって実行されます。
したがって、この意味で(一般的な実装は何をするのか)、Pythonは「解釈された言語」であり、C#とJavaが次の場合に限ります。これらはすべて、最初にバイトコードを生成し、次にVM/インタープリターを介して実行するという一般的な実装戦略を持っています。 。
おそらく、編集プロセスがいかに「重く」、遅く、そして儀式的であるかに焦点が当てられています。CPythonは、可能な限り高速で、可能な限り軽量で、可能な限り少ないセレモニーでコンパイルするように設計されています。コンパイラーはエラーチェックと最適化をほとんど行わないため、高速かつ少量のメモリで実行できます。ほとんどの場合、コンパイルが実行されていることをユーザーが意識する必要がなく、必要なときにいつでも自動的かつ透過的に実行されます。JavaとC#は通常、エラーをより徹底的にチェックし、より多くの最適化を実行するために、コンパイル中により多くの作業を受け入れます(したがって、自動コンパイルを実行しません)。これは灰色のスケールの連続体であり、黒または白の状況ではありません。
これらには、Pythonインタープリターがソースをコンパイルするバイトコードが含まれています。このコードは、Pythonの仮想マシンによって実行されます。
Pythonのドキュメントでは、次のような定義について説明しています。
Pythonは、コンパイルされた言語とは対照的に、インタプリタ言語ですが、バイトコードコンパイラが存在するため、区別があいまいになる可能性があります。これは、実行可能ファイルを明示的に作成せずにソースファイルを直接実行できることを意味します。
通訳言語のようなものはありません。インタプリタとコンパイラのどちらを使用するかは、純粋に実装の特徴であり、言語とはまったく関係ありません。
すべての言語は、インタプリタまたはコンパイラのいずれかで実装できます。大多数の言語には、各タイプの実装が少なくとも1つあります。(たとえば、CおよびC ++用のインタープリターがあり、JavaScript、PHP、Perl、Python、Ruby用のコンパイラーがあります。)さらに、最新の言語実装の大部分は、実際にはインタープリターとコンパイラー(または複数のコンパイラー)の両方を組み合わせています。
言語は、抽象的な数学的規則のセットにすぎません。インタプリタは、言語のいくつかの具体的な実装戦略の1つです。これらの2つは、完全に異なる抽象化レベルで動作します。英語が型付き言語である場合、「解釈された言語」という用語は型エラーになります。「Pythonはインタプリタ言語です」というステートメントは、単にfalseであるだけでなく(falseであるということは、たとえ間違っていても、ステートメントが意味をなさないことを意味するため)、言語を次のように定義することはできないため、単純に意味をなさないのです。 「通訳」
特に、現在存在するPython実装を見ると、次のような実装戦略が使用されています。
そのリストにあるすべての実装(および、tinypy、Shedskin、Psycoなど、私が言及しなかった他のいくつかの実装)にはコンパイラーが含まれていることに気付くかもしれません。実際、私が知る限り、純粋に解釈されるPython実装は現在ありません。そのような実装は計画されておらず、そのような実装はこれまでありませんでした。
「通訳された言語」という用語は意味をなさないだけでなく、「通訳された実装を備えた言語」を意味すると解釈しても、明らかに真実ではありません。あなたにそれを言った人は誰でも、明らかに彼が何について話しているのか分かりません。
特に、.pyc
表示されているファイルは、CPython、Stackless Python、またはUnladenSwallowによって生成されたキャッシュされたバイトコードファイルです。
これらは、.py
ファイルがインポートされるときにPythonインタープリターによって作成され、インポートされたモジュール/プログラムの「コンパイルされたバイトコード」が含まれます。これは、ソースコードからバイトコードへの「変換」(1回だけ実行する必要がある)という考え方です。が対応するファイルよりも新しい場合は、後続import
のsでスキップできるため、起動が少し速くなります。しかし、それはまだ解釈されています。.pyc
.py
モジュールの読み込みを高速化するために、Pythonはモジュールのコンパイル済みコンテンツを.pycにキャッシュします。
CPythonは、ソースコードを「バイトコード」にコンパイルします。パフォーマンス上の理由から、ソースファイルに変更が加えられるたびに、このバイトコードがファイルシステムにキャッシュされます。これにより、コンパイルフェーズをバイパスできるため、Pythonモジュールの読み込みがはるかに高速になります。ソースファイルがfoo.pyの場合、CPythonはバイトコードをソースのすぐ隣のfoo.pycファイルにキャッシュします。
python3では、Pythonのインポート機構が拡張され、すべてのPythonパッケージディレクトリ内の単一のディレクトリにバイトコードキャッシュファイルを書き込んで検索します。このディレクトリは__pycache__と呼ばれます。
モジュールのロード方法を説明するフローチャートは次のとおりです。
詳細については:
ref:PEP3147
ref:「コンパイルされた」Pythonファイル
これは初心者向けです、
Pythonは、スクリプトを実行する前に、スクリプトをコンパイル済みコード、いわゆるバイトコードに自動的にコンパイルします。
スクリプトの実行はインポートとは見なされず、.pycは作成されません。
たとえば、別のモジュールxyz.pyをインポートするスクリプトファイルabc.pyがある場合、abc.pyを実行すると、xyzがインポートされるためxyz.pycが作成されますが、abc以降はabc.pycファイルは作成されません。 pyはインポートされていません。
インポートされていないモジュールの.pycファイルを作成する必要がある場合は、py_compile
およびcompileall
モジュールを使用できます。
モジュールは、任意のpy_compile
モジュールを手動でコンパイルできます。1つの方法はpy_compile.compile
、そのモジュールの関数をインタラクティブに使用することです。
>>> import py_compile
>>> py_compile.compile('abc.py')
これにより、.pycがabc.pyと同じ場所に書き込まれます(オプションのパラメーターでオーバーライドできますcfile
)。
compileallモジュールを使用して、1つまたは複数のディレクトリ内のすべてのファイルを自動的にコンパイルすることもできます。
python -m compileall
ディレクトリ名(この例では現在のディレクトリ)を省略した場合、モジュールはにあるすべてのものをコンパイルします。sys.path
Python(少なくとも最も一般的な実装)は、元のソースをバイトコードにコンパイルしてから、仮想マシンでバイトコードを解釈するというパターンに従います。これは、(ここでも、最も一般的な実装)が純粋なインタープリターでも純粋なコンパイラーでもないことを意味します。
ただし、これの反対側は、コンパイルプロセスがほとんど隠されていることです。.pycファイルは基本的にキャッシュのように扱われます。それらは物事をスピードアップしますが、通常はそれらをまったく意識する必要はありません。必要に応じて、ファイルの時刻/日付スタンプに基づいて、それらを自動的に無効にして再ロード(ソースコードを再コンパイル)します。
これに関する問題が発生したのは、コンパイルされたバイトコードファイルが将来的にタイムスタンプを取得したときだけでした。つまり、ソースファイルよりも常に新しいように見えました。見た目が新しくなったため、ソースファイルが再コンパイルされることはなく、どのような変更を加えても無視されました...
Pythonの*.pyファイルは、数行のコードを記述した単なるテキストファイルです。「pythonfilename.py」などを使用してこのファイルを実行しようとすると
このコマンドは、Python仮想マシンを呼び出します。Python仮想マシンには、「コンパイラ」と「インタプリタ」の2つのコンポーネントがあります。インタプリタは*.pyファイルのテキストを直接読み取ることができないため、このテキストは最初にPVM (ハードウェアではなくPVM)を対象とするバイトコードに変換されます。PVMはこのバイトコードを実行します。* .pycファイルも、シェル内のファイルまたはその他のファイルでインポート操作を実行する実行の一部として生成されます。
この*.pycファイルがすでに生成されている場合、次に* .pyファイルを実行/実行するたびに、システムはコンパイルを必要としない* .pycファイルを直接ロードします(これにより、プロセッサのマシンサイクルが節約されます)。
* .pycファイルが生成されると、編集しない限り、*。pyファイルは必要ありません。
tldr; これはソースコードから変換されたコードであり、PythonVMが実行のために解釈します。
ボトムアップの理解:プログラムの最終段階は、ハードウェア/マシン上でプログラムの命令を実行/実行することです。したがって、実行前の段階は次のとおりです。
CPUでの実行/実行
bytcodeをマシンコードに変換します。
機械語は変換の最終段階です。
CPUで実行される命令は、マシンコードで示されます。マシンコードはCPUから直接実行できます。
バイトコードをマシンコードに変換します。
ソースコードをbytcodeに変換します。
今、実際のプロット。これらのステージのいずれかを実行する場合、2つのアプローチがあります。コードを一度に変換[または実行]する(別名コンパイル)と、コードを1行ずつ変換[または実行]する(別名解釈)。
たとえば、ソースコードをbytcoeにコンパイルし、バイトコードをマシンコードにコンパイルし、マシンコードを解釈して実行することができます。
言語の一部の実装では、効率を上げるためにステージ3をスキップします。つまり、ソースコードをマシンコードにコンパイルしてから、マシンコードを解釈して実行します。
一部の実装では、すべての中間ステップをスキップし、実行のためにソースコードを直接解釈します。
現代語では、通訳のコンパイルと通訳の両方が必要になることがよくあります。
たとえば、JAVAは、ソースコードをbytcodeにコンパイルし[JAVAソースがbytcodeとして格納される方法]、bytcodeをマシンコードにコンパイルし[JVMを使用]、マシンコードを解釈して実行します。[したがって、JVMはOSごとに異なる方法で実装されますが、JVMがインストールされている異なるOSで同じJAVAソースコードを実行できます。]
たとえば、Pythonは、ソースコードをbytcodeにコンパイルし[通常、.pyソースコードに付随する.pycファイルとして検出されます]、bytocdeをマシンコードにコンパイルします[PVMなどの仮想マシンによって実行され、結果は実行可能ファイルになります]、マシンを解釈しますコード/実行可能ファイル。
言語が解釈またはコンパイルされていると言えるのはいつですか?
したがって、JAVAとPythonはインタプリタ言語です。
bytcodeをマシンコードに変換する第3段階が原因で、混乱が生じる可能性があります。多くの場合、これは仮想マシンと呼ばれるソフトウェアを使用して行われます。仮想マシンがマシンのように動作するために混乱が発生しますが、実際にはそうではありません。移植性のために仮想マシンが導入されています。任意のREALマシンにVMを配置すると、同じソースコードを実行できるようになります。ほとんどのVMで使用されているアプローチ[これは第3段階です]はコンパイル中であるため、コンパイルされた言語であると言う人もいます。VMの重要性については、そのような言語はコンパイルされ、解釈されるとよく言われます。
Pythonコードは2つの段階を経ます。最初のステップでは、コードを実際にはバイトコードである.pycファイルにコンパイルします。次に、この.pycファイル(バイトコード)はCPythonインタープリターを使用して解釈されます。このリンクを参照してください。ここでは、コードのコンパイルと実行のプロセスを簡単に説明します。
その重要な区別言語仕様と言語実装:
コンパイラは、フロントエンドとバックエンドの2つの独立した部分で構成されています。フロントエンドはソースコードを受け取り、それを検証して中間コードに変換します。その後、バックエンドはそれをマシンコードに変換して、物理マシンまたは仮想マシンで実行します。インタプリタはコンパイラですが、この場合、仮想マシンで直接中間コードを実行する方法を生成できます。Pythonコードを実行するには、必要に応じてコードを中間コードに変換します。その後、コードはfile.pycに格納できるバイトコードとして「アセンブル」されるため、実行するたびにプログラムのモジュールをコンパイルする必要はありません。 。このアセンブルされたPythonコードは、次を使用して表示できます。
from dis import dis
def a(): pass
dis(a)
C言語へのインタプリタを構築できるように、誰でもPython言語で静的バイナリへのコンパイラを構築できます。コンパイラーの構築プロセスを単純化および自動化するためのツール(lex / yacc )があります。
マシンは英語やその他の言語を理解しません。バイトコードのみを理解します。バイトコードはコンパイル(C / C ++、Javaなど)またはインタプリタ(Ruby、Pythonなど)する必要があります。.pycはキャッシュされたバージョンです。バイトコード。 https://www.geeksforgeeks.org/difference-between-compiled-and-interpreted-language/ コンパイルされた言語と解釈された言語の違いについて簡単に説明します。TLDRは解釈された言語であり、すべてをコンパイルする必要はありません。実行時のコードであるため、ほとんどの場合、入力などに厳密ではありません。