Как запретить python использовать осиротевшие файлы .pyc? (те, у которых нет соответствующих файлов .py)

Время от времени я сталкиваюсь с очень трудной для отладки проблемой: где-то в моем $PYTHONPATH есть оставшийся файл .pyc, а соответствующий файл .py был перемещен в другое место, которое находится позже в $PYTHONPATH, поэтому, когда я пытаюсь для импорта модуля используется «осиротевший» файл .pyc, и все изменения в «настоящем» файле .py игнорируются, что оставляет меня в невероятном замешательстве, пока я не выясню, что происходит.

Есть ли способ заставить python не использовать «осиротевшие» файлы .pyc или выводить предупреждение при их использовании?
В качестве альтернативы, означает ли тот факт, что у меня есть эта проблема, что я делать что-то не так, и если да, то что?


person weronika    schedule 28.05.2012    source источник
comment
Это НЕ удалит файлы pyc из подкаталогов (оболочка сначала расширяет *.pyc, прежде чем команда rm увидит аргументы). вместо этого используйте find * -name '*.pyc' | xargs rm -f. Примечание 1. Я использую find *, а не find ., чтобы .git и т. д. не искались, 2. Я удаляю все файлы pyc, поскольку python, похоже, только проверяет, что исходный код старше, чем скомпилированные файлы, а не точно соответствует времени мода (поскольку это не соответствует mtime при создании файлов pyc - по крайней мере, под Linux).   -  person iheggie    schedule 21.11.2014
comment
find . -name '*pyc' -delete - видимо find стоит флаг удаления найденных файлов   -  person vlad-ardelean    schedule 06.05.2015


Ответы (2)


Попробуйте это (см. здесь):

PYTHONDONTWRITEBYTECODE

Если это установлено, Python не будет пытаться записывать файлы .pyc или .pyo при импорте исходных модулей. Это эквивалентно указанию опции -B.

Новое в версии 2.6.

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

person zizozu    schedule 28.05.2012
comment
Это предотвращает запись новых файлов .pyc, но предотвращает ли это их загрузку python? - person Martijn Pieters; 28.05.2012
comment
Это не мешает Python загружать существующие файлы .pyc. Я только что проверил это с Python 2.6.8 и 2.7.3. - person Martijn Pieters; 28.05.2012
comment
Я боялся, что это были мои единственные варианты... Однако полезно знать о переменной env PYTHONDNTWRITEBYTECODE! Я могу использовать это сейчас (после удаления всех существующих файлов .pyc), пока я не напишу сценарий очистки и не вставлю его в свой cron или что-то в этом роде. - person weronika; 29.05.2012

Вы не можете запретить Python загружать файлы .pyc, если он находит их на своем пути, нет.

У вас есть несколько вариантов:

  1. Импортируйте проблемный модуль и выясните, каков его путь:

    >>> import borkenmod
    >>> import sys
    >>> sys.modules[borkenmod.__name__].__file__
    'lib/python2.7/borkenmod.pyc'
    
  2. Используйте скрипт , чтобы пройти PYTHONPATH и удалить устаревшие файлы байт-кода. Связанный скрипт удаляет все .pyc файлы, для которых нет соответствующего .py файла.

  3. Сотрите все файлы .pyc в вашем PYTHONPATH, и пусть Python регенерирует их с помощью compileall модуля:

    python -m compileall [path]
    

    затем удалите этот файл.

Обратите внимание, что последние два варианта могут привести к удалению законных модулей Python! Некоторые модули Python (особенно с коммерческой лицензией) распространяются только в виде скомпилированного байт-кода.

person Martijn Pieters    schedule 28.05.2012
comment
Wipe+compileall, вероятно, является излишним - я, вероятно, должен просто написать что-нибудь, чтобы стереть только осиротевшие. Спасибо за трюк с sys.modules! Это должно пригодиться - по крайней мере, когда я выясню, что загружается не тот файл. - person weronika; 29.05.2012