Як уникнути .pyc файлів?


268

Чи можу я запустити інтерпретатор python, не генеруючи зібрані файли .pyc?

Відповіді:


288

З розділу "Що нового в Python 2.6 - зміни інтерпретатора" :

Тепер Python може бути заборонено писати файли .pyc або .pyo, поставивши перемикач -B на інтерпретатор Python, або встановивши змінну середовища PYTHONDONTWRITEBYTECODE перед запуском інтерпретатора. Цей параметр доступний для програм Python як sys.dont_write_bytecodeзмінна, і код Python може змінити значення для зміни поведінки інтерпретатора.

Оновлення 2010-11-27: Python 3.2 вирішує проблему захаращеності папок з .pycфайлами, вводячи спеціальну __pycache__підпапку, див. Що нового в Python 3.2 - PYC Repository Directories .


1
Принаймні, на OS X 10.8 під керуванням Python 2.7 змінна середовища не впливає.
sorin

5
Якщо ви вбудовуєте інтерпретатор (у програму C ++), використовуйте "Py_DontWriteBytecodeFlag = 1;" у своєму вихідному коді. Це глобальний int, оголошений у pydebug.h.
JimB

1
Змінна середовища працює для мене чудово в 2.7, не знаю, які проблеми мають інші. Дякую!
Томас

8
Працював і для мене на OSX (10,8 та 10,10); @sorin Ви експортували цю змінну належним чином? export PYTHONDONTWRITEBYTECODE=1
nevelis

1
Чи знаєте ви, як зробити те ж саме з pytest?

110
import sys

sys.dont_write_bytecode = True

25
Я просто спробував це, і він працює для імпортних модулів. Зокрема, після встановлення цієї змінної все, що імпортується пізніше, не створюватиме файли pyc. Це приємно. Дякую.

Замість того, щоб додати це в батьківський модуль, спробуйте додати це у посиланні сценарію. Це працює круто. Завдяки @te Вілсона
Sathy

4
Додайте це до свого, site-packages/usercustomize.pyщоб це стосувалося всіх ваших сценаріїв. Для мене цей каталог був $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Ср. docs.python.org/2/tutorial/…
RobM

3
Мій пакунок сайтів знаходився за адресою: /usr/local/lib/python2.7/site-packages, і мені довелося створити usercustomize.py
anon58192932

3
Або в один рядок:import sys; sys.dont_write_bytecode = True
ET-CS

23

Насправді є спосіб зробити це в Python 2.3+, але це трохи езотерично. Я не знаю, чи розумієте ви це, але ви можете зробити наступне:

$ unzip -l /tmp/example.zip
 Archive:  /tmp/example.zip
   Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32) 
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'

За даними бібліотеки zipimport :

У архіві ZIP можуть бути будь-які файли, але для імпорту доступні лише файли .py та .py [co]. Імпорт ZIP динамічних модулів (.pyd, .so) заборонений. Зауважте, що якщо архів містить лише файли .py, Python не намагатиметься змінити архів, додавши відповідний файл .pyc або .pyo, тобто, якщо ZIP-архів не містить файлів .pyc, імпорт може бути досить повільним.

Таким чином, все, що вам потрібно зробити, - це скопіювати файли, додати zipfile до свого sys.path та потім імпортувати їх.

Якщо ви будуєте це для UNIX, ви можете також розглянути можливість упаковки сценарію за допомогою цього рецепта: виконувану програму unix zip , але зауважте, що вам, можливо, доведеться підправити це, якщо ви плануєте використовувати stdin чи читати що-небудь з sys.args (це МОЖЕ бути зроблено без зайвих клопотів).

На мій досвід, продуктивність не надто страждає через це, але ви повинні подумати двічі, перш ніж імпортувати будь-які дуже великі модулі таким чином.


11

У версії 2.5 немає можливості її придушити, крім заходів, таких як не давати користувачам запису доступу до каталогу.

У python 2.6 та 3.0, однак, може бути встановлено в модулі sys під назвою "dont_write_bytecode", який можна встановити для придушення цього. Це також можна встановити, передавши параметр "-B" або встановивши змінну середовища "PYTHONDONTWRITEBYTECODE"


7

Ви можете встановити sys.dont_write_bytecode = Trueу своєму джерелі, але це повинно бути в першому завантаженому файлі python. Якщо ви стратите, python somefile.pyто не отримаєте somefile.pyc.

При встановленні утиліти за допомогою, setup.pyі entry_points=ви будете встановлені sys.dont_write_bytecodeв сценарії запуску. Таким чином, ви не можете покластися на сценарій запуску "за замовчуванням", створений налаштуваннями.

Якщо ви запускаєте Python з файлу python як аргумент самостійно, ви можете вказати -B:

python -B somefile.py

somefile.pycне буде генеровано в будь-якому випадку, але жодні .pycфайли для інших файлів, які також імпортовані.

Якщо у вас є якась утиліта, myutilі ви не можете її змінити, вона не передасть -B інтерпретатору python. Просто запустіть його, встановивши змінну середовища PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil

4

У мене в тестовому наборі є кілька тестових випадків, і до того, як я запустив тестовий набір у терміналі Mac, такий:

python LoginSuite.py

Запускаючи команду таким чином, у моєму каталозі було заповнено файли .pyc. Я спробував описаний нижче метод, і це вирішило проблему:

python -B LoginSuite.py

Цей метод працює, якщо ви імпортуєте тестові випадки у тестовий набір та запускаєте набір у командному рядку.


4

Починаючи з Python 3.8, ви можете використовувати змінну середовища PYTHONPYCACHEPREFIXдля визначення каталогу кешу для Python.

З документів Python:

Якщо це встановлено, Python записуватиме файли .pyc у дерево дзеркальних каталогів на цьому шляху, а не в каталоги pycache у вихідному дереві. Це еквівалентно визначенню параметра -X pycache_prefix = PATH.

Приклад

Якщо ви додасте наступний рядок до свого ./profile в Linux:

export PYTHONPYCACHEPREFIX="$HOME/.cache/cpython/"

Python не створить дратівливих __pycache__каталогів у вашому каталозі проектів, натомість він поставить їх усі~/.cache/cpython/


2

Ви можете зробити каталоги, що ваші модулі існують лише для читання для користувача, яким працює інтерпретатор Python.

Я не думаю, що є більш елегантний варіант. PEP 304 схоже, була спробою ввести простий варіант для цього, але, схоже, це було відмовлено.

Я думаю, що, мабуть, існує якась інша проблема, яку ви намагаєтеся вирішити, і для якої відключення .py [co] виявиться вирішенням, але, мабуть, краще буде атакувати будь-яку оригінальну проблему замість цього.


2

Рішення для ipython 6.2.1 using python 3.5.2(Тестовано на Ubuntu 16.04 та Windows 10):

Ipythonне поважає, %env PYTHONDONTWRITEBYTECODE =1якщо встановлено в ipythonінтерпретаторі або під час запуску в ~/.ipython/profile-default/startup/00-startup.ipy. Натомість використовуйте наступне у своєму~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True

0

Наскільки я знаю, python буде збирати всі модулі, які ви "імпортуєте". Однак python НЕ буде компілювати запуск сценарію python, використовуючи: "python script.py" (однак він буде компілювати будь-які модулі, які імпортує скрипт).

Справжні питання, чому ви не хочете, щоб python збирав модулі? Можливо, ви могли б автоматизувати спосіб їх очищення, якщо вони заважають.


Я часто виявляв, що є застарілі .pycфайли байт-кодів . З якоїсь причини, коли я змінюю клас / модуль, .pycфайл не оновлюється. Тож коли я імпортую його після зміни .pyфайлу, він все одно буде використовувати .pycфайл, що призводить до помилок
alpha_989
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.