Коли файли .pyc оновлюються?


91

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

  1. Після модифікації файлів "py" поведінка програми змінюється. Це вказує на те, що файли "py" компілюються або, принаймні, виконуються через якийсь хеш-процес або порівнюються позначки часу, щоб визначити, чи слід їх повторно компілювати.
  2. Після видалення всіх ".pyc" файлів ( rm *.pyc) іноді поведінка програми змінюється. Що свідчить про те, що вони не компілюються під час оновлення файлів ".py".

Запитання:

  • Як вони вирішують, коли їх складати?
  • Чи є спосіб переконатися, що під час розробки вони перевіряють суворіше?

14
Остерігайтеся видалення файлів .pyc за допомогою rm *.pyc. Це не призведе до видалення файлів .pyc у вкладених папках. Використовуйте find . -name '*.pyc' -deleteзамість цього
Загс

6
Можливо, одна примітка щодо вашого запитання: Програма не працює набагато швидше, коли її читають із файлу '.pyc' або '.pyo', ніж коли вона читається з файлу '.py'; єдине, що швидше стосується файлів .pyc або .pyo, - це швидкість завантаження. посилання
Меггі

@maggie яка різниця між часом завантаження та виконання?
Даніель Спрінгер

3
Завантаження @Dani - це час, необхідний для читання та компіляції програми. Час виконання - це час, коли програма фактично запускається, що відбувається після завантаження. Якщо ви хочете бути технічним, типи часу - це час завантаження, час компіляції, час посилання та час виконання. Створення .pyc виключає частину часу компіляції.
Ерік Клієн,

@EricKlien дякує людині
Даніель Спрінгер

Відповіді:


79

Ці .pycфайли створюються (і , можливо , переписані) тільки тоді , коли цей файл пітон імпортується який - або інший сценарій. Якщо імпортується імпорт, Python перевіряє, чи .pycвнутрішня мітка часу файлу не старша за відповідний .pyфайл. Якщо це так, він завантажує .pyc; якщо його немає або якщо файл .pycще не існує, Python компілює .pyфайл у файл .pycі завантажує його.

Що ви маєте на увазі під "суворішою перевіркою"?


3
Я можу виправити проблеми з rm *.pyc. Я знаю, що якщо я змушую відтворити всі файли, то деякі проблеми виправляються, що вказує на те, що файли не перекомпілюються самі по собі. Я припускаю, що якщо вони все-таки використовують мітки часу, тоді немає можливості зробити цю поведінку жорсткішою, але проблема все ще зберігається.
Аарон Шиф,

13
Це не зовсім правильно. Мітки часу не повинні збігатися (і, як правило, не). У .pyc«мітка часу ПОВИННО бути старше , ніж відповідний .py» мітки часу s , щоб викликати перекомпіляції.
Тім Піцкер

4
@Aaron, Ви, можливо, змінюєте файли .py і в процесі їх старіння (наприклад, копіюючи їх з іншого каталогу, використовуючи операцію, яка зберігає "час модифікації")?
greggo

1
@greggo, я використовую git та оновлення із сховища, так що так, я є певним чином. Це могло б це зробити. Дякую.
Аарон Шиф,

1
Добре знати. Як щодо того, щоб виправити свою відповідь тоді?
Piotr Dobrogost

29

Файли .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-файли з проекту?


Msgstr "При перетворенні модуля (папки з __init__.pyфайлом) ...". Це був би пакет, а не модуль.
Роберт Девід Грант,

2
Зокрема, __init__.pycостанки. - Як це? Оскільки пакет є каталогом, видалення пакета означає видалення каталогу, отже, файлів не залишилось ...
Piotr Dobrogost

3
@PiotrDobrogost Правильно керований контроль над джерелом передбачає неперевірку ваших файлів pyc у вихідні. Тому, хоча ви можете видалити папку, включаючи файли pyc, у вашій локальній копії, вона не буде видалена для когось іншого, хто робить git-тяга. Це може зірвати ваш сервер, якщо ваше розгортання також включає git pull.
Загс

Є багато причин не довіряти своєму середовищу розробників бути репрезентативним для того, де ваш код буде розгорнутий. Ця .pycпроблема також є однією з причин: приховані залежності від рівня ОС та рівнів виправлень утиліти, .soфайли, конфігураційні файли, інші бібліотеки Python (якщо ви не працюєте у віртуальному env), незрозумілі env vars ... список можна продовжувати. Щоб бути ретельним і знайти всі подібні проблеми, вам потрібно зробити чисту копію коду в репозиторії git або опублікувати як пакет на сервері стилю PyPi, а також виконати повний клон або налаштування на новій ВМ. Деякі з цих потенційних проблем роблять це .pycпитання блідим у порівнянні.
Chris Johnson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.