Как избежать файлов .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 .

Constantin
источник
1
По крайней мере, в OS X 10.8 с Python 2.7 переменная окружения не влияет.
сорин
5
Если вы встраиваете интерпретатор (в программе на C ++), используйте «Py_DontWriteBytecodeFlag = 1;» в вашем исходном коде. Это глобальный int, объявленный в pydebug.h.
JimB
1
Переменная окружения прекрасно работает для меня в 2.7, не знаю, какие проблемы возникают у других. Спасибо!
Томас,
8
У меня тоже работал на OSX (10.8 и 10.10); @sorin вы правильно экспортировали переменную? export PYTHONDONTWRITEBYTECODE=1
Невелис
1
Вы знаете, как сделать то же самое с pytest?
110
import sys

sys.dont_write_bytecode = True
Те Уилсон
источник
25
Я только что попробовал, и он работает для импортированных модулей. В частности, после установки этой переменной все, что будет импортировано позже, не будет генерировать pyc-файлы. Это восхитительно. Спасибо.
Вместо того, чтобы добавить это в родительский модуль, попробуйте добавить это в ссылочном скрипте. Это работает круто. Благодаря @te Уилсон
Сати
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]. Импорт динамических модулей (.pyd, .so) в ZIP запрещен. Обратите внимание, что если архив содержит только файлы .py, Python не будет пытаться изменить архив, добавляя соответствующий файл .pyc или .pyo, а это означает, что если архив ZIP не содержит файлов .pyc, импорт может быть довольно медленным.

Таким образом, все, что вам нужно сделать, это заархивировать файлы, добавить zip-файл в ваш sys.path и затем импортировать их.

Если вы создаете это для UNIX, вы можете также рассмотреть возможность упаковки вашего скрипта с использованием этого рецепта: исполняемый файл zix unix , но учтите, что вам, возможно, придется настроить его, если вы планируете использовать 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в сценарии запуска. Таким образом, вы не можете полагаться на сценарий запуска по умолчанию, сгенерированный setuptools.

Если вы запускаете Python с файлом python в качестве аргумента самостоятельно, вы можете указать -B:

python -B somefile.py

somefile.pycв любом случае не будет сгенерирован, но .pycфайлы для других файлов тоже не будут импортированы.

Если у вас есть какая-то утилита myutilи вы не можете ее изменить, она не передаст -B интерпретатору python. Просто запустите его, установив переменную окружения PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil
Elwyne
источник
4

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

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/

Rotareti
источник
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
alpha_989
источник
0

Насколько я знаю, Python скомпилирует все модули, которые вы "импортируете". Однако python НЕ будет компилировать скрипт python, запущенный с использованием: "python script.py" (однако он скомпилирует все модули, которые импортирует скрипт).

Реальный вопрос в том, почему вы не хотите, чтобы python компилировал модули? Вы могли бы, вероятно, автоматизировать способ очистки, если они мешают.

Alex
источник
Я часто нахожу, что есть устаревшие .pycфайлы байт-кода . По какой-то причине, когда я меняю класс / модуль, .pycфайл не обновляется. Поэтому, когда я импортирую его после изменения .pyфайла, он все равно будет использовать .pycфайл, что приведет к ошибкам
alpha_989