Когда обновляются файлы .pyc?

Я понимаю, что файлы ".pyc" - это скомпилированные версии файлов ".py" с открытым текстом, созданные во время выполнения, для ускорения работы программ. Однако я заметил несколько вещей:

  • При изменении файлов "py" изменение поведения программы. Это указывает на то, что файлы "py" скомпилированы или, по крайней мере, идут через какой-то процесс хеширования или сравнивают метки времени, чтобы определить, следует ли их повторно скомпилировать.
  • При удалении всех файлов ".pyc" (rm *.pyc) иногда изменяется поведение программы. Это означает, что они не компилируются при обновлении ".py".

Вопросы:

  • Как они решают, когда компилироваться?
  • Есть ли способ обеспечить более строгую проверку во время разработки?

Ответ 1

Файлы .pyc создаются (и, возможно, перезаписываются) только тогда, когда этот файл python импортируется каким-либо другим script. Если вызывается импорт, Python проверяет, соответствует ли внутренняя метка файла .pyc соответствующему файлу .py. Если это так, он загружает .pyc; если это не так или если .pyc еще не существует, Python компилирует файл .py в .pyc и загружает его.

Что вы подразумеваете под "более строгой проверкой"?

Ответ 2

.pyc файлы, созданные при каждом импортировании соответствующих элементов кода, и обновляются, если соответствующие файлы кода были обновлены. Если файлы .pyc будут удалены, они будут автоматически восстановлены. Тем не менее, они не автоматически удаляются при удалении соответствующих файлов кода.

Это может вызвать некоторые действительно забавные ошибки в рефакторе уровня файла.

Прежде всего, вы можете в конечном итоге надавить код, который работает только на вашем компьютере и ни на кого другом. Если у вас есть оборванные ссылки на удаленные файлы, они все равно будут работать локально, если вы не вручную удалите соответствующие файлы .pyc, потому что файлы .pyc могут использоваться в импорте. Это усугубляется тем фактом, что правильно сконфигурированная система управления версиями будет только толкать файлы .py в центральный репозиторий, а не файлы .pyc, что означает, что ваш код может передать "тест импорта" (все импортирует хорошо) просто отлично, а не работать на любом другом компьютере.

Во-вторых, у вас могут быть довольно ужасные ошибки, если вы превращаете пакеты в модули. Когда вы конвертируете пакет (папку с файлом __init__.py) в модуль (файл .py), файлы .pyc, которые когда-то представляли этот пакет, остаются. В частности, остается __init__.pyc. Итак, если у вас есть пакет foo с некоторым кодом, который не имеет значения, то позже удалите этот пакет и создайте файл foo.py с помощью некоторой функции def bar(): pass и запустите:

from foo import bar

вы получаете:

ImportError: cannot import name bar

потому что python все еще использует старые .pyc файлы из пакета foo, ни один из которых не определяет bar. Это может быть особенно проблематично на веб-сервере, где полностью функционирующий код может сломаться из-за файлов .pyc.

В результате обеих этих причин (и, возможно, других) код развертывания и код тестирования должны удалять файлы .pyc, например, со следующей строкой bash:

find . -name '*.pyc' -delete

Кроме того, с python 2.6 вы можете запустить python с флагом -B, чтобы не использовать файлы .pyc. См. Как избежать .pyc файлов? для получения более подробной информации.

Смотрите также: Как удалить все .pyc файлы из проекта?