ホームページ >バックエンド開発 >Python チュートリアル >Python プログラムの実行プロセスには、ソース コードをバイトコードに変換 (つまりコンパイル) し、バイトコードを実行することが含まれます。
私たちは、テキストを処理したり、システム管理作業を行ったりするために、毎日いくつかの Python プログラムを作成する必要があります。プログラムを作成した後は、Python コマンドを入力してプログラムを起動し、実行を開始するだけです。
$ python some-program.py
では、テキスト形式の .py ファイルを、どのようにして段階的に変換できるものに変換するのでしょうか。 CPU によって実行されますか? 機械語命令はどうですか?また、プログラムの実行中に .pyc ファイルが生成されることがありますが、これらのファイルの機能は何ですか?
Python は動作的にはシェル スクリプトのようなインタプリタ言語に似ていますが、実際には、Python プログラムの実行原理は Java や Java と本質的に同じです。 C# と 仮想マシン および バイトコード について要約できます。 Python は 2 つのステップでプログラムを実行します。まずプログラム コードをバイトコードにコンパイルし、次に仮想マシンを起動してバイトコードを実行します。
Python コマンドは、 Python インタープリターですが、他のスクリプト言語インタープリターとは根本的に異なります。実際、Python インタプリタは コンパイラ と 仮想マシン で構成されます。 Python インタプリタが開始されると、主に次の 2 つのステップが実行されます:
コンパイラは、.py ファイル内の Python ソース コードをバイトコードにコンパイルし、仮想マシンはコンパイラによって生成されたバイトコードを 1 行ずつ実行します。
したがって、.py ファイル内の Python ステートメントは、機械語命令に直接変換されるのではなく、Python バイトコードに変換されます。
Python プログラムのコンパイル結果はバイトコードであり、Python の動作に関連する多くの内容が含まれています。したがって、Python 仮想マシンの動作メカニズムを深く理解する場合でも、Python プログラムの動作効率を最適化する場合でも、バイトコードは重要なコンテンツです。では、Python のバイトコードはどのようなものでしょうか? Python プログラムのバイトコードはどのように取得できますか? Python には、ソース コードを即座にコンパイルするための組み込み関数 apply が用意されています。コンパイル対象のソースコードをパラメータとしてcompile関数を呼び出すだけで、ソースコードのコンパイル結果を取得できます。
以下では、compile 関数を使用してプログラムをコンパイルします:
ソース コードは、demo.py ファイルに保存されます:
PI = 3.14 def circle_area(r): return PI * r ** 2 class Person(object): def __init__(self, name): self.name = name def say(self): print('i am', self.name)
コンパイル 以前は、ソース コードをファイルから読み取る必要がありました:
>>> text = open('D:\myspace\code\pythonCode\mix\demo.py').read() >>> print(text) PI = 3.14 def circle_area(r): return PI * r ** 2 class Person(object): def __init__(self, name): self.name = name def say(self): print('i am', self.name)
次に、コンパイル関数を呼び出してソース コードをコンパイルします:
>>> result = compile(text,'D:\myspace\code\pythonCode\mix\demo.py', 'exec')
コンパイルには 3 つの必須パラメーターがあります。 function:
source : コンパイルするソース コード
filename: ソース コードが配置されているファイル名
mode: コンパイル モード。exec は、ソース コードをコンパイルすることを意味します。 module
exec: モジュールのソース コードをコンパイルするために使用されます
single: 単一の Python ステートメントを (対話的に) コンパイルするために使用されます
eval : eval 式のコンパイルに使用されます
コンパイル関数を通じて、最終的なソース コードのコンパイル結果結果を取得します:
>>> result <code object <module> at 0x000001DEC2FCF680, file "D:\myspace\code\pythonCode\mix\demo.py", line 1> >>> result.__class__ <class 'code'>
最後にコード タイプを取得しますオブジェクトであり、その対応する基礎構造は PyCodeObject です。
PyCodeObject のソース コードは次のとおりです。
/* Bytecode object */ struct PyCodeObject { PyObject_HEAD int co_argcount; /* #arguments, except *args */ int co_posonlyargcount; /* #positional only arguments */ int co_kwonlyargcount; /* #keyword only arguments */ int co_nlocals; /* #local variables */ int co_stacksize; /* #entries needed for evaluation stack */ int co_flags; /* CO_..., see below */ int co_firstlineno; /* first source line number */ PyObject *co_code; /* instruction opcodes */ PyObject *co_consts; /* list (constants used) */ PyObject *co_names; /* list of strings (names used) */ PyObject *co_varnames; /* tuple of strings (local variable names) */ PyObject *co_freevars; /* tuple of strings (free variable names) */ PyObject *co_cellvars; /* tuple of strings (cell variable names) */ /* The rest aren't used in either hash or comparisons, except for co_name, used in both. This is done to preserve the name and line number for tracebacks and debuggers; otherwise, constant de-duplication would collapse identical functions/lambdas defined on different lines. */ Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */ PyObject *co_filename; /* unicode (where it was loaded from) */ PyObject *co_name; /* unicode (name, for reference) */ PyObject *co_linetable; /* string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details. */ void *co_zombieframe; /* for optimization only (see frameobject.c) */ PyObject *co_weakreflist; /* to support weakrefs to code objects */ /* Scratch space for extra data relating to the code object. Type is a void* to keep the format private in codeobject.c to force people to go through the proper APIs. */ void *co_extra; /* Per opcodes just-in-time cache * * To reduce cache size, we use indirect mapping from opcode index to * cache object: * cache = co_opcache[co_opcache_map[next_instr - first_instr] - 1] */ // co_opcache_map is indexed by (next_instr - first_instr). // * 0 means there is no cache for this opcode. // * n > 0 means there is cache in co_opcache[n-1]. unsigned char *co_opcache_map; _PyOpcache *co_opcache; int co_opcache_flag; // used to determine when create a cache. unsigned char co_opcache_size; // length of co_opcache. };
コード オブジェクト PyCodeObject は、バイトコードと定数、名前、コードに関係するものなど。主要なフィールドは次のとおりです:
Purpose | |
---|---|
パラメータの数 | |
キーワードパラメータの数 | |
変数の部分的な数 | |
コードの実行に必要なスタック領域 | |
識別 | |
コードブロックの最初の行番号 | |
命令オペレーションコード、つまりバイトコード | #co_consts |
co_names | |
co_varnames | |
以上がPython プログラムの実行プロセスには、ソース コードをバイトコードに変換 (つまりコンパイル) し、バイトコードを実行することが含まれます。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。