Pythonコードの解析とpycファイル
このガイドでは、PythonファイルがGraalVM Pythonランタイムでどのように解析されるかについて詳しく説明します。
pycファイルの作成および管理
目的の.py
ファイルと一致する.pyc
ファイルが見つからないか、無効なファイルが見つかった場合、.pyc
ファイルはGraalVM Pythonランタイムによって自動的に作成されます。
Pythonソース・ファイル(モジュール)が最初の実行中にインポートされたときに、適切な.pyc
ファイルが自動的に作成されます。同じモジュールが再度インポートされたときには、すでに作成されている.pyc
ファイルが使用されます。つまり、まだ実行(インポート)されていないソース・ファイルについては.pyc
ファイルはありません。.pyc
ファイルの作成は完全にFileSystem APIを介して行われ、埋込み担当者はファイルシステム・アクセスを管理できます。
その後、スクリプトを実行するたびに、既存の.pyc
ファイルが再利用されるか、新しいものが生成されます。元のソース・ファイルのタイムスタンプまたはハッシュコードが変更されると、.pyc
ファイルが再生成されます。ハッシュコードは、source.hashCode()
をコールすることによってPythonソースに基づいてのみ生成され、java.util.Arrays.hashCode(byte[])
で計算された、ソース・ファイル・バイトの配列に対するJDKハッシュコードです。
.pyc
ファイルは、Pythonパーサーのマジック番号が変更された場合にも再生成されます。マジック番号はPythonソースでハードコードされており、ユーザーが変更することはできません(当然ながら、そのユーザーがPythonのバイトコードへのアクセス権を持っている場合を除きます)。
GraalVMのPythonランタイムの開発者は、バイトコード形式が変更されたときにマジック番号を変更します。これは実装の詳細であるため、マジック番号はGraalVMのPythonランタイムのバージョンに対応している必要はありません(CPythonの場合と同様)。pycのマジック番号は、実行されている具体的なPythonランタイムJavaコードに応じて変わります。
.pyc
ファイルを使用する場合、バージョンを切り替えるときまたは元のソース・コードを変更するときには少なくともGraalVMのPythonランタイムへの書込みアクセスを許可する必要があります。そうしないと、ソース・ファイルの再生成が失敗し、インポートのたびに、古い.pyc
ファイルへのアクセス、コードの解析、そのシリアライズ、および新しい.pyc
ファイルの記述の試行(および失敗)というオーバーヘッドが発生します。
*.pyc
ファイルは、GraalVMのPythonランタイムによって削除されることはなく、再生成されるのみです。これは、該当するソース・ファイルが変更されたとき(内容の最終変更のタイムスタンプまたはハッシュコード)、またはPython実装パーサーのマジック番号が変更されたときに再生成されます。マジック番号の変更はリリース・ノートで通知されるため、埋込み担当者またはシステム管理者はアップグレード時に古い.pyc
ファイルを削除できます。
.pyc
ファイルについて作成されるフォルダ構造は次のようになります:
top_folder
__pycache__
sourceA.graalpy.pyc
sourceB.graalpy.pyc
sourceA.py
sourceB.py
sub_folder
__pycache__
sourceX.graalpy.pyc
sourceX.py
デフォルトでは、__pycache__
ディレクトリはソース・コード・ファイルと同じディレクトリ・レベルに作成され、このディレクトリに、同じディレクトリのすべての.pyc
ファイルが格納されます。このフォルダには、異なるバージョンのPython (CPythonなどを含む)で作成された.pyc
ファイルが格納されることがあるため、ユーザーには、*.cpython3-6.pyc
などで終わるファイルが表示される場合があります。
.pyc
ファイルは主に、CPythonと互換性のある方法でランタイムによって自動的に管理されます。CPythonの場合と同様に、それらの場所と、それらを記述する必要があるかどうかを指定するオプションがあり、これらのオプションの両方をゲスト・コードで変更できます。
*.pyc
ファイルの作成は、CPythonの場合と同じ方法で制御できます(https://docs.python.org/3/using/cmdline.htmlを参照):
- GraalVMのPythonランチャ(
graalpy
)は、PYTHONDONTWRITEBYTECODE
環境変数を読み取ります。これが空でない文字列に設定されている場合、Pythonはモジュールのインポート時に.pyc
ファイルの記述を試行しません。 - ランチャのコマンドライン・オプション
-B
を指定した場合、前述のものと同じ効果があります。 - ゲスト言語コードは、実行時に
sys
組込みモジュールの属性dont_write_bytecode
を変更して、後続のインポートの動作を変更できます。 - ランチャは、
PYTHONPYCACHEPREFIX
環境変数を読み取ります。設定すると、接頭辞が指すパスに__pycache__
ディレクトリが作成され、ソース・ツリーのディレクトリ構造のミラーがオンデマンドで作成されて.pyc
ファイルが格納されます。 - ゲスト言語コードは、実行時に
sys
モジュールの属性pycache_prefix
を変更して、後続のインポートの場所を変更できます。
埋込み担当者は、環境変数またはCPythonオプションを使用してこれらのオプションをGraalVMのPythonの実装に通信することはできないため、これらのオプションを次の言語オプションとして使用できます:
python.DontWriteBytecodeFlag
--B
またはPYTHONDONTWRITEBYTECODE
と同等python.PyCachePrefix
-PYTHONPYCACHEPREFIX
と同等
Pythonコンテキストでは、.pyc
ファイルの記述がデフォルトで有効になりません。graalpy
ランチャによってこれがデフォルトで有効になりますが、埋込みユースケースでこれが必要な場合は、__pycache__
の場所が適切に管理され、その場所にあるファイルが導出元のソース.py
ファイルと同様に操作に対して保護されるように注意を払う必要があります。
また、アプリケーション・ソースをGraalVM EntepriseのPythonランタイムにアップグレードするには、埋込み担当者が必要に応じて古い.pyc
ファイルを削除する必要があります。
セキュリティに関する考慮事項
ファイル操作(データおよびタイムスタンプの取得やpyc
ファイルの記述)はすべて、FileSystem APIを介して行われます。埋込み担当者は、カスタム(読取り専用など)のFileSystem
実装を使用して、これらの操作すべてを変更できます。また、埋込み担当者は、GraalVMのPythonランタイムについてI/O権限を無効にすることにより、.pyc
ファイルの作成を事実上無効にすることもできます。
.pyc
ファイルが読取り可能でない場合、その場所は書込み可能ではありません。.pyc
ファイルのシリアライズ・データまたはマジック番号がなんらかの形で破損している場合、デシリアライズは失敗し、単に.py
ファイルが再度解析されます。これによって、モジュールの解析についてのみ、パフォーマンスにわずかな影響が生じますが、ほとんどのアプリケーションにとって重大ではありません(アプリケーションがPythonコードのロード以外に実際の作業を行う場合)。