Como evitar arquivos .pyc?

268

Posso executar o interpretador python sem gerar os arquivos .pyc compilados?

Avner
fonte

Respostas:

288

Em "Novidades do Python 2.6 - Alterações de intérpretes" :

Agora, o Python pode ser impedido de gravar arquivos .pyc ou .pyo, fornecendo a opção -B ao interpretador Python ou definindo a variável de ambiente PYTHONDONTWRITEBYTECODE antes de executar o interpretador. Essa configuração está disponível para os programas Python como a sys.dont_write_bytecodevariável e o código Python pode alterar o valor para modificar o comportamento do intérprete.

Atualização 27-11-2010: O Python 3.2 soluciona o problema de bagunçar as pastas de origem com os .pycarquivos, introduzindo uma __pycache__subpasta especial , consulte Novidades do Python 3.2 - Diretórios de repositórios PYC .

Constantin
fonte
1
Pelo menos no OS X 10.8 executando o Python 2.7, a variável de ambiente não tem efeito.
22612 Sorin
5
Se você estiver incorporando o intérprete (em um programa C ++), use "Py_DontWriteBytecodeFlag = 1;" no seu código-fonte. Esse é um int global declarado em pydebug.h.
JimB
1
A variável de ambiente funciona muito bem para mim no 2.7, não sei que problemas os outros estão tendo. Obrigado!
Thomas
8
Trabalhei para mim também no OSX (10.8 e 10.10); @sorin você exportou a variável corretamente? export PYTHONDONTWRITEBYTECODE=1
Nevelis
1
Você sabe fazer o mesmo com o pytest?
110
import sys

sys.dont_write_bytecode = True
te wilson
fonte
25
Eu apenas tentei isso e funciona para módulos importados. Especificamente, uma vez que essa variável é configurada, qualquer coisa importada posteriormente não gera arquivos pyc. Isso é delicioso. Obrigado.
Em vez de adicionar isso no módulo pai, tente adicionar isso no script mencionado. Isso funciona bem. Obrigado a @te wilson
Sathy
4
Adicione isso ao seu site-packages/usercustomize.pypara aplicar isso a todos os seus scripts. Para mim, esse diretório era $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Cf. docs.python.org/2/tutorial/…
RobM
3
Meu site-packages foi localizado em: /usr/local/lib/python2.7/site-packages e eu tive que criar usercustomize.py
anon58192932
3
Ou em uma linha:import sys; sys.dont_write_bytecode = True
ET-CS
23

Na verdade, existe uma maneira de fazer isso no Python 2.3+, mas é um pouco esotérico. Não sei se você percebeu isso, mas você pode fazer o seguinte:

$ 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'

De acordo com a biblioteca zipimport :

Qualquer arquivo pode estar presente no arquivo ZIP, mas apenas os arquivos .py e .py [co] estão disponíveis para importação. A importação ZIP de módulos dinâmicos (.pyd, .so) não é permitida. Observe que, se um arquivo compactado contiver apenas arquivos .py, o Python não tentará modificá-lo adicionando o arquivo .pyc ou .pyo correspondente, o que significa que se um arquivo ZIP não contiver arquivos .pyc, a importação poderá ser bastante lenta.

Portanto, tudo o que você precisa fazer é compactar os arquivos, adicionar o arquivo zip ao seu sys.path e importá-los.

Se você estiver criando isso para o UNIX, considere também empacotar seu script usando esta receita: executável zip do unix , mas observe que pode ser necessário ajustar isso se você planeja usar o stdin ou ler qualquer coisa do sys.args (pode ser feito sem muita dificuldade).

Na minha experiência, o desempenho não sofre muito por causa disso, mas você deve pensar duas vezes antes de importar módulos muito grandes dessa maneira.

Jason Baker
fonte
11

Na versão 2.5, não há como suprimi-lo, exceto medidas como não dar aos usuários acesso de gravação ao diretório.

No python 2.6 e 3.0, no entanto, pode haver uma configuração no módulo sys chamada "dont_write_bytecode" que pode ser configurada para suprimir isso. Isso também pode ser definido passando a opção "-B" ou configurando a variável de ambiente "PYTHONDONTWRITEBYTECODE"

Brian
fonte
7

Você pode definir sys.dont_write_bytecode = Truesua fonte, mas isso deve estar no primeiro arquivo python carregado. Se você executar python somefile.py, você não receberá somefile.pyc.

Quando você instala um utilitário usando setup.pye entry_points=você configurou sys.dont_write_bytecodeo script de inicialização. Portanto, você não pode confiar no script de inicialização "padrão" gerado pelo setuptools.

Se você iniciar o Python com o arquivo python como argumento, poderá especificar -B:

python -B somefile.py

somefile.pycnão seria gerado de qualquer maneira, mas também não há .pycarquivos para outros arquivos importados.

Se você tiver algum utilitário myutile não puder mudar isso, ele não passará -B para o interpretador python. Basta iniciar definindo a variável de ambiente PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil
Elwyne
fonte
4

Eu tenho vários casos de teste em um conjunto de testes e antes de executar o conjunto de testes no Mac Terminal desta maneira:

python LoginSuite.py

Executando o comando dessa maneira, meu diretório estava sendo preenchido com arquivos .pyc. Tentei o método indicado abaixo e resolveu o problema:

python -B LoginSuite.py

Este método funciona se você estiver importando casos de teste para o conjunto de testes e executando o conjunto na linha de comandos.

Ravil Asadov
fonte
4

A partir do Python 3.8, você pode usar a variável de ambiente PYTHONPYCACHEPREFIXpara definir um diretório de cache para o Python.

Nos documentos do Python:

Se isso estiver definido, o Python gravará arquivos .pyc em uma árvore de diretórios espelhados nesse caminho, em vez de nos diretórios pycache da árvore de origem. Isso é equivalente a especificar a opção -X pycache_prefix = PATH.

Exemplo

Se você adicionar a seguinte linha ao seu ./profileno Linux:

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

O Python não criará os __pycache__diretórios irritantes no diretório do seu projeto, mas colocará todos eles em~/.cache/cpython/

Rotareti
fonte
2

Você pode criar os diretórios em que seus módulos existem somente leitura para o usuário em que o interpretador Python está executando.

Eu não acho que haja uma opção mais elegante. O PEP 304 parece ter sido uma tentativa de introduzir uma opção simples para isso, mas parece ter sido abandonado.

Imagino que provavelmente haja outro problema que você está tentando resolver, para o qual desativar .py [co] pareceria uma solução alternativa, mas provavelmente será melhor atacar qualquer que seja esse problema original.

Logan
fonte
2

Solução para ipython 6.2.1 using python 3.5.2(Testado no Ubuntu 16.04 e Windows 10):

Ipythonnão respeita %env PYTHONDONTWRITEBYTECODE =1se definido no ipythonintérprete ou durante a inicialização em ~/.ipython/profile-default/startup/00-startup.ipy. Em vez disso, use o seguinte em seu~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True
alpha_989
fonte
0

Tanto quanto eu sei, o python irá compilar todos os módulos que você "importa". No entanto, o python NÃO compila um script python executado usando: "python script.py" (no entanto, compila todos os módulos importados pelo script).

A verdadeira questão é por que você não quer que o python compile os módulos? Você provavelmente poderia automatizar uma maneira de limpá-las se elas estiverem atrapalhando.

Alex
fonte
Descobri frequentemente que existem .pycarquivos antigos de bytecode . Por algum motivo, quando altero a classe / módulo, o .pycarquivo não é atualizado. Então, quando eu importá-lo depois de alterar o .pyarquivo, ele ainda vai usar o .pycarquivo, levando a erros
alpha_989