Сделать Python игнорировать файлы .pyc
Есть ли способ заставить Python игнорировать любые .pyc файлы, которые присутствуют и всегда интерпретировать весь код (включая импортированные модули) напрямую? Google не получил никаких ответов, поэтому я подозреваю, что нет, но, на всякий случай, стоило спросить.
(Почему я хочу это сделать? У меня есть большой конвейер сценариев Python, которые повторяются несколько раз в кластере из нескольких сотен компьютеров. Скрипты Python сами живут в общей файловой системе NFS. Почему-то редко были запущены сотни раз в течение нескольких часов, они внезапно начнут сбой с ошибкой в том, что вы не сможете импортировать модуль. Принуждение к регенерации файла .pyc устраняет проблему. Я хочу, конечно, исправить основные причины, но в то же время нам также нужна система для продолжения работы, поэтому кажется, что игнорирование файлов .pyc, если возможно, было бы разумным обходным решением).
P.S. Я использую Python 2.5, поэтому я не могу использовать -B.
Ответы
Ответ 1
Вы можете использовать стандартный модуль библиотеки библиотеки Python для переопределения __builtins__.__import__
, который является функцией hook, вызываемой оператором import
и from
. В частности, функция imp.load_module может использоваться для загрузки .py
, даже если присутствует соответствующий .pyc
. Обязательно внимательно изучите все документы на странице, на которую я указал, плюс те, что указаны для import, так как это вид деликатной работы. Однако сами документы предлагают использовать импортные крючки (на PEP 302), но для этой конкретной задачи я подозреваю, что это будет еще сложнее.
Кстати, вероятные причины для ваших наблюдаемых проблем включают условия гонки между разными компьютерами, пытающимися одновременно писать файлы .pyc
. Блокировка NFS, как известно, flaky и всегда была;-). Пока каждый компилятор Python, который вы используете, находится в одной и той же версии (если нет, у вас большие проблемы;), я предпочел бы прекомпилировать все эти файлы .py
в .pyc
и сделать их каталоги только для чтения; последний, по-видимому, самый простой подход (а не взлом __import__
), даже если по какой-то причине вы не можете прекомпилировать.
Ответ 2
Это не совсем то, что вы просили, но удалили бы существующие файлы .pyc, а затем не создавали для вас больше работы? В этом случае вы можете использовать опцию -B:
>python --help
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-B : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x
Ответ 3
Если кто-то использует python 2.6 или выше с тем же вопросом, самое простое:
- Удалить все .pyc файлы
- Запустите все ваши интерпретаторы python с опцией
-B
, чтобы они не генерировали файлы .pyc.
Из документов:
-B Если дано, Python не будет пытаться писать файлы .pyc или .pyo при импорте исходных модулей. См. Также PYTHONDONTWRITEBYTECODE.
Новое в версии 2.6.
Если вы не можете удалить все .pycs, вы можете:
1) Запустите все ваши интерпретаторы python с параметрами -B -O
.
Это скажет python искать .pyo файлы для байт-кода вместо файлов .pyc(-O
) и скажет python не генерировать файлы байт-кода (-B
).
Комбинация двух опций, если вы не использовали их раньше, заключается в том, что Python не будет генерировать файлы байт-кода и не будет искать файлы байт-кода, которые были бы сгенерированы более старыми запусками.
Из документов:
-B Если дано, Python не будет пытаться писать файлы .pyc или .pyo при импорте исходных модулей. См. Также PYTHONDONTWRITEBYTECODE.
Новое в версии 2.6.
-O Включите основные оптимизации. Это изменяет расширение имени файла для скомпилированных (байткодов) файлов с .pyc на .pyo. См. Также PYTHONOPTIMIZE.
Ответ 4
Возможно, вы могли бы обойти это, например, планируя задание, чтобы периодически закрывать скрипты и удалять файлы .pyc.
Ответ 5
Ну, я не думаю, что Python когда-либо интерпретирует код напрямую, если вы загружаете код из файла. Даже при использовании интерактивной оболочки Python скомпилирует импортированный модуль в .pyc.
Тем не менее, вы можете написать оболочку script, чтобы продолжить и удалить все файлы .pyc перед запуском своих скриптов. Это наверняка заставило бы полную перестройку перед каждым исполнением.
Ответ 6
Вы можете найти PEP 3147 - Справочники репозитория PYC, представляющие большой интерес для Python 3.2 и далее.