Bug ou comportamento indesejado?
Postado por Osvaldo Santana
Estou trabalhando na construção do pacote do Python 2.4.2 para a plataforma Maemo e uma das nossas missões nesse projeto é fazer com que os pacotes com o Python ocupem pouco espaço em disco. Essa missão vem do fato que a plataforma Maemo é projetada para dispositivos móveis que não costumam ser construídos com discos muito grande.
Para reduzir essa ocupação de espaço resolvemos distribuir apenas os módulos otimizados (.pyo) da biblioteca Python porque esses arquivos são menores que os seus equivalentes em código fonte (.py) que serão distribuídos em um pacote separado específico para desenvolvedores. Outra mudança que fizemos foi distribuir esses pacotes dentro de um arquivo .zip.
No entanto, descobrimos posteriormente que o FS do N770 já é comprimido e colocar os módulos dentro desse .zip se tornou desnecessário. Enquanto eu ‘tirava’ os módulos de dentro do ZIP eu esbarrei numa inconsistência no comportamento do CPython que vou ilustrar na seção abaixo:
- Primeiramente eu crio dois módulos compilados. Um deles com otimização e o outro sem e adiciono os mesmos dentro de um ZIP:
$ ls modulo_c.pyc modulo_o.pyo $ zip modulos.zip modulo_o.pyo modulo_c.pyc adding: modulo_o.pyo (deflated 38%) adding: modulo_c.pyc (deflated 38%) $ ls modulo_c.pyc modulo_o.pyo modulos.zip
- Depois aciono o interpretador em modo normal (não-otimizado):
$ python2.4 >>> import modulo_c modulo_c >>> import modulo_o ImportError: No module named modulo_o
Como puderam observar, o interpretador Python não procura arquivos com a extensão .pyo quando está em modo não-otimizado.
- Na seqüência eu aciono o interpretador em modo otimizado:
$ python2.4 -O >>> import modulo_c ImportError: No module named modulo_c >>> import modulo_o modulo_o
E o comportamento inverso pode ser observado. O interpretador também não procura módulos .pyc quando está em modo otimizado.
- Removo os módulos .pyc e .pyo para ficar com eles apenas dentro do Zip e repito os passos anteriores dizendo que o ‘modulos.zip’ agora faz parte do PYTHONPATH e deve servir de local para procura de módulos Python:
$ rm *.pyc *.pyo $ ls modulos.zip $ PYTHONPATH=modulos.zip python2.4 >>> import modulo_c modulo_c >>> import modulo_o modulo_o $ PYTHONPATH=modulos.zip python2.4 -O >>> import modulo_c modulo_c >>> import modulo_o modulo_o
Aqui está a inconsistência. Utilizando o hook zipimport do Python ele procura por módulos .pyc e .pyo no PYTHONPATH. A única distinção que ele faz entre os dois modos é a de que no modo normal o interpretador procura na ordem “py->pyc->pyo” e no modo otimizado ele procura na ordem “py->pyo->pyc”.
Acho que essa inconsistência tem que ser eliminada e, em minha humilde opinião o comportamento do hook zipimport é mais adequado do que o do primeiro porque poderemos encontrar casos onde bibliotecas bytecode sejam fornecidas como .pyo e .pyc misturados (ok, eu sei que só renomear o arquivo já que o bytecode é o mesmo, mas não acho essa solução muito ‘elegante’).
Estou preparando um patch para deixar o comportamento do hook de importação padrão do Python funcione de maneira equivalente ao hook zipimport e vou submetê-lo para o projeto. Mas como esse patch tem uma solução baseada na minha visão eu gostaria de saber antes a opinião dos leitores: Qual dos 2 comportamentos deve permanecer? E, isso deve ser mudado?
9 Responses to “Bug ou comportamento indesejado?”
Deixe um comentário







novembro 1st, 2005 at 11:36 am
Realmente esse comportamento nao eh consistente.
Eu concordo que o comportamento do zipimport eh o mais adequado.
Eu ja tropecei no mesmo problema mas nao tinha notado que o zipimport se comportava de forma diferente. Seria otimo se isso fosse consertado.
novembro 1st, 2005 at 11:43 am
Trackback to Internet Tablet Users blog: http://www.internettablettalk.com/blog/?p=130
novembro 1st, 2005 at 12:06 pm
Sidnei,
Eu criei um patch de sugestão em
http://pymaemo.sourceforge.net/cgi-bin/moin.cgi/OsvaldoSantanaNeto
Roger,
Thanks for the quote in your blog. I’ll try to publish my posts in english in near future to make reader’s life easier
novembro 1st, 2005 at 1:02 pm
Eu também acho o comportamento incoerente.
Sobre o Patch, legal, mas alguns comentários que podem te ajudar a tê-lo aceito:
- if (strcmp(filetab->suffix, “.pyc”) == 0)
+ if (strcmp(filetab->suffix, “.pyc”) == 0) {
filetab->suffix = “.pyo”;
+ continue;
+ }
+ if (strcmp(filetab->suffix, “.pyo”) == 0) {
+ filetab->suffix = “.pyc”;
+ continue;
+ }
pode ser substituído por:
+ else if (strcmp(filetab->suffix, “.pyo”) == 0)
+ filetab->suffix = “.pyc”;
eliminando os “continue“.
Depois, tem algo não relevante, em “/* Try .py */” juntamente com a linha em branco acima. Idem para “/* Try pyo/pyc */” e as mudanças em whitespace no bloco todo! Aliás, a repetição deste bloco deveria ser feita dentro do primeiro, para os valores diferentes “(!Py_OptimizeFlag)“, você está conferindo a mesma coisa duas vezes! :-).
Tirar o “/* XXX INDT */” ajuda
strcpy() is harmful! Troque por:
strncpy(module_filename, filename, MAXPATHLEN);
module_filename[ MAXPATHLEN ] = ”; /* vide man strncpy por que */
com isso a comparação “strlen(module_filename) ” torna-se sempre verdadeira (no seu código atual se ela for falsa –> SEGFAULT!)
Então você deve trocar a comparação por MAXPATHLEN-1, para caber o “c” ou “o” da extensão.
Uma pequena optimização nesta última parte é fazer:
size_t l = strlen( module_filename );
if ( l
eliminando, assim, cópia desnecessária das strings e ainda chamadas de função.
Valeu!
novembro 1st, 2005 at 2:22 pm
Aqui não é um local muito agradável para discutir patches mas vamos lá

Já mudei o patch para usar ‘else if’ e tirei os continues. Pra você ver como fazer um patch ‘nas coxas’ só aumenta o trabalho
Não entendi o que você quis dizer no parágrafo que fala sobre espaços em branco e sobre os testes duplicados (criei uma thread lá na lista, vamos mudar a discussão pra lá?)
strcpy(): Eu sei que é harmful, mas mantive a mesma construção do original. Sim, o import.c original usa strcpy() e a verificação de “strlen()
novembro 1st, 2005 at 2:24 pm
Ah! e eu comentei no meu e-mail que iria retirar as referências à INDT do patch

novembro 1st, 2005 at 4:49 pm
Qual lista você mandou o email? Na python brasil ainda não chegou nada.
Bom, manda o patch renovado para lá que eu vejo o que ficou “faltando”
novembro 1st, 2005 at 5:05 pm
Ok, vou mandar pra lá, mas já chegou na lista sim:
http://thread.gmane.org/gmane.comp.python.brasil/12593
novembro 4th, 2005 at 1:15 am
Is the work you are doing going to apply to the S60 smartphones too? From the announcements yesterday, it seems that Nokia is settling on python as its language of choice.
Alas for me. I am one of those who found python hazy and ruby clear, so I turned down the ruby path and know nothing of python.
Roger