.pycファイルはいつ更新されますか?


91

「.pyc」ファイルは、プログラムをより高速に実行するために実行時に作成される、平文の「.py」ファイルのコンパイル済みバージョンであることを理解しています。しかし、私はいくつかのことを観察しました:

  1. 「py」ファイルを変更すると、プログラムの動作が変わります。これは、「py」ファイルがコンパイルされるか、少なくとも何らかのハッシュプロセスを実行するか、タイムスタンプを比較して、再コンパイルする必要があるかどうかを判断することを示します。
  2. すべての「.pyc」ファイル(rm *.pyc)を削除すると、プログラムの動作が変わる場合があります。これは、「。py」の更新時にコンパイルされていないことを示します。

質問:

  • いつコンパイルするかをどのように決定しますか?
  • 開発中にそれらがより厳密にチェックされることを保証する方法はありますか?

14
で.pycファイルを削除しないように注意してくださいrm *.pyc。ネストされたフォルダ内の.pycファイルは削除されません。find . -name '*.pyc' -delete代わりに使用
Zags

6
おそらくあなたの質問に関する1つのメモ:「.pyc」ファイルまたは「.pyo」ファイルから読み取られたプログラムは、「。py」ファイルから読み取られたプログラムよりも速く実行されません。「.pyc」または「.pyo」ファイルの方が高速なのは、ファイルの読み込み速度だけです。リンク
マギー

@maggieロード時間と実行時間の違いは何ですか?
Daniel Springer

3
@Daniの読み込みは、プログラムの読み取りとコンパイルにかかる時間です。実行時間は、プログラムが実際に実行されているときで、ロード後に発生します。技術的になりたい場合、時間タイプはロード時間、コンパイル時間、リンク時間、実行時間です。.pycを作成すると、コンパイル時の部分がなくなります。
Eric Klien

@EricKlien感謝の言葉
ダニエルスプリンガー

回答:


79

.pycファイルは、Pythonのファイルが他のスクリプトによってインポートされた場合にのみ作成(そしておそらく上書き)されています。インポートが呼び出されると、Pythonは.pycファイルの内部タイムスタンプが対応する.pyファイルよりも古いかどうかを確認します。もしそうなら、それはロードし.pycます。.pyc存在しない場合、または存在しない場合、Pythonは.pyファイルをにコンパイルして.pycロードします。

「より厳密なチェック」とはどういう意味ですか?


3
の問題を修正できますrm *.pyc。すべてのファイルを強制的に再作成すると、いくつかの問題が修正され、ファイル自体が再コンパイルされていないことがわかります。彼らがタイムスタンプを使用する場合、この動作をより厳密にする方法はないと思いますが、問題はまだ解決しません。
アーロン・シフ2013

13
これは正しくありません。タイムスタンプは一致する必要はありません(通常、一致しません)。.pycタイムスタンプでなければならない古い対応するよりも.py"再コンパイルをトリガするためのタイムスタンプ。
Tim Pietzcker 2013

4
@Aaron、.pyファイルを変更している可能性がありますか?その過程でそれらを古くしていますか(たとえば、「変更時刻」を保持する操作を使用して、別のディレクトリからコピーすることによって)?
greggo 2013

1
@greggo、私はgitを使用してリポジトリから更新しているので、そうです。それはそれを行うことができます。ありがとう。
アーロン・シフ2013

1
知ってよかった。それではあなたの答えを修正するのはどうですか?
Piotr Dobrogost 2017

29

対応するコード要素がインポートされるたびに生成され、対応するコードファイルが更新されている場合は更新される.pycファイル。.pycファイルを削除すると、自動的に再生成されます。ただし、ません対応するコードファイルが削除され自動的には削除され。

これは、ファイルレベルのリファクタリング中にいくつかの本当に楽しいバグを引き起こす可能性があります。

まず、自分のマシンでのみ機能し、他の人では機能しないコードをプッシュすることになります。削除したファイルへの参照がぶら下がっている場合、.pycファイルはインポートで使用できるため、関連する.pycファイルを手動で削除しない限り、これらはローカルで機能します。これは、適切に構成されたバージョン管理システムが.pyファイルを中央リポジトリにプッシュするだけで、.pycファイルはプッシュしないという事実と相まって、コードは「インポートテスト」に合格でき(すべてのインポートが正常に実行されます)、問題なく成功します。他人のコンピュータで作業する。

次に、パッケージをモジュールに変換すると、かなりひどいバグが発生する可能性があります。パッケージ(__init__.pyファイルのあるフォルダー)をモジュール(.pyファイル)に変換すると、そのパッケージを表す.pycファイルが残ります。特に、__init__.pyc遺跡。したがって、重要ではないコードを含むパッケージfooがある場合は、後でそのパッケージを削除し、いくつかの関数def bar(): passを含むファイルfoo.pyを作成して実行します。

from foo import bar

あなたが得る:

ImportError: cannot import name bar

Pythonはまだfooパッケージの古い.pycファイルを使用しているため、どれもbarを定義していません。これは、.pycファイルが原因で完全に機能するコードが破損する可能性があるWebサーバーで特に問題になる可能性があります。

これらの両方の理由(および場合によってはその他の理由)の結果として、次のbashの行のように、デプロイメントコードとテストコードで.pycファイルを削除する必要があります。

find . -name '*.pyc' -delete

また、Python 2.6以降では、Pythonを -B .pycファイルを使用しないようにフラグを設定ます。.pycファイルを回避する方法を参照してください詳細については。

参照:プロジェクトからすべての.pycファイルを削除するにはどうすればよいですか?


「モジュール(__init__.pyファイルのあるフォルダー)を変換するとき...」それはモジュールではなくパッケージです。
Robert David Grant

2
特に、__init__.pyc遺跡。- どうして?パッケージはディレクトリを削除するパッケージ手段を削除するディレクトリであるとして、これファイルはありません...左
ピョートルDobrogost

3
@PiotrDobrogost適切に管理されたソース管理には、pycファイルをソースにチェックインしないことが含まれます。そのため、ローカルコピーのpycファイルを含むフォルダーを削除することはできますが、git pullを実行する他のユーザーが削除することはありません。デプロイにgit pullも含まれている場合、サーバーがクラッシュする可能性があります。
Zags

コードがデプロイされる場所の代表として開発環境を信頼しない多くの理由があります。この.pyc問題も理由の1つです。OSとユーティリティのパッチレベル、.soファイル、構成ファイル、その他のPythonライブラリへの隠された依存関係(仮想環境で実行していない場合)、あいまいな環境変数...リストは続きます。このような問題を徹底して見つけるには、gitリポジトリにコードのクリーンコピーを作成するか、パッケージとしてP​​yPiスタイルのサーバーに公開し、完全なクローンを作成するか、新しいVMでセットアップする必要があります。これらの潜在的な問題のいくつかは、この.pyc問題を比較すると見苦しくします。
クリスジョンソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.