Quando um novo virtualenv é criado, há várias coisas instaladas nele. Uma dessas coisas é o instalador do pacote python, pip.
No Linux, o executável pip é um script de shell. No topo deste script de shell pip está uma linha shebang (#!) Que especifica o interpretador python no virtualenv. Esta linha contém o caminho absoluto para o interpretador python.
Se o caminho absoluto para o interpretador python no virtualenv for muito longo (nomes de caminhos profundamente aninhados e / ou grandes), ele pode exceder o comprimento máximo permitido para uma linha shebang.
O comprimento máximo para uma linha shebang é limitado no kernel por BINPRM_BUF_SIZE, definido em /usr/include/linux/binfmts.h. Nas máquinas Linux que examinei, esse limite é definido como 128.
Portanto, quando o caminho para onde um virtualenv python é criado se torna muito longo, usar o pip do virtualenv não funcionará. Ele falhará com o erro: "mau intérprete: arquivo ou diretório inexistente"
Uma solução alternativa para esse problema é não executar o pip diretamente, mas executar o interpretador python do virtualenv e passar o script pip para o python como a fonte a ser executada.
Também estou enfrentando esse problema.
Eu também.
Obrigado pela solução alternativa!
Observe que os scripts de wrapper são, na verdade, gerados por setuptools (se você instalar a partir do sdist) ou distlib (se você instalar a partir do wheel). Portanto, qualquer correção para esse problema deve ser solicitada a esses projetos.
Mas se for uma limitação do sistema operacional, talvez simplesmente _não_ haja uma solução viável? Parece que me lembro que uma vez, Perl usou um encantamento mágico para executar scripts (googles um pouco ...) Sim, algo assim (traduzido para Python)
#!/bin/sh
eval 'exec /the/long/interpreter/path/to/python $0 ${1+"$@"}'
Você precisaria de algumas coisas extras para que o Python não tentasse executar a linha eval-exec, mas isso pode funcionar.
Se alguém quisesse propor algo assim como uma solicitação de recurso para ferramentas de configuração e distlib, isso seria ótimo.
Portanto, quando o caminho para onde um virtualenv python é criado se torna muito longo, usar o pip do virtualenv não funcionará.
Seria _realmente_ bom se executando virtualenv
em um sistema no qual este problema ocorre, o comando geraria algum aviso (ou até mesmo um erro) de que estar em um diretório com um nome de caminho tão longo essencialmente não é suportado por os padrões no momento.
Eu estou acertando isso também. É especificamente um problema para mim, pois estou executando pip
de dentro das compilações do Jenkins, que têm caminhos _muito_ longos para o pwd. Curiosamente, eu tenho vários escravos de construção construídos de forma idêntica (todos têm BINPRM_BUF_SIZE definido como 128 e o mesmo pip e python e versões de virtualenv) e estou experimentando isso em alguns deles, mas não em outros, mesmo com comprimentos de caminho variáveis.
Eu gosto da sugestão de @b-long; se virtualenv
vai criar um invólucro que não funciona no sistema atual, deve pelo menos dar ao usuário um aviso, se não for uma falha total.
Não está claro como o virtualenv poderia detectar essa situação. Não podemos usar exatamente um valor de um cabeçalho C e não sei como detectaríamos que estamos em um sistema com essa limitação (o Windows não tem, tem OSX?)
Estou inclinado a encerrar esse problema como uma limitação do sistema operacional, não um problema do virtualenv.
Para valer a pena, algumas reflexões ...
ctypes
fazer isso?# on Linux, BINPRM_BUF_SIZE == 128, giving us a maximum shebang length of 127
# 2 bytes for #!, 11 bytes for '/bin/python' leaves us with 114
if sys.platform() == 'Linux' and len(home_dir) > 114:
log.warn("bin/activate may not work your system, as the length of the shebang line will exceed 128 characters")
Tenho certeza de que outros usuários também gostariam da mudança que sugeri. Podemos deixar isso aberto para comentários e para inspirar um PR? Obrigado @jantman e @pfmoore : smile:
BINPRM_BUF_SIZE
é definido em um cabeçalho do kernel e parece ser usado apenas por um pequeno punhado de funções do kernel. Não acredito que haja alguma maneira de detectar isso programaticamente (além da leitura nos cabeçalhos, o que não é nem de perto viável).
Dito isso, acho que é razoável supor que isso não mudará tão cedo (há uma rápida visão geral do comprimento máximo do shebang aqui ). O comprimento atual também é claramente fornecido na seção "Notas" da página do manual execve (2) , onde afirma: "Um comprimento máximo de linha de 127 caracteres é permitido para a primeira linha em um script de shell #! Executável."
Eu presumiria que todos os sistemas operacionais compatíveis com POSIX têm algum tipo de limite, embora pareça que alguns deles, especificamente as variantes do BSD, podem ter limites acima de 8.000 caracteres.
Embora pareça uma solução razoável simplesmente codificar algo tão ingênuo quanto minha sugestão acima (se a plataforma for Linux e a linha tiver mais de 127 caracteres), parece excessivamente rude, específico e inflexível para mim.
Ainda estou pensando em como eu testaria isso programaticamente de uma forma que não adicionasse muita sobrecarga a virtualenv
(concedido, só precisaríamos testar isso no momento da criação de venv, então eu ' d assumir que alguma sobrecarga pode ser aceitável).
Eu tenho um código simples de prova de conceito para testar se um determinado caminho é ou não um comprimento aceitável, mas é bastante feio, pois grava um arquivo no disco e, em seguida, executa o arquivo para capturar a saída. O exemplo e a saída estão aqui: https://gist.github.com/jantman/ba39f98936643bc948bd
Vou ter que encerrar a noite, mas vou tentar voltar a isso. Eu certamente apreciaria a contribuição de qualquer outro usuário Linux, ou usuários de outros sistemas operacionais, que possam confirmar se eles têm ou não um limite semelhante.
Em vez de tentar fazer algo complicado como fazer suposições sobre o limite, por que não apenas fazer um script bash de teste funcional? Se o python for invocado corretamente, então tudo está bem, caso contrário, não é.
Reiterar:
setuptools
e distlib
se quiser que isso seja corrigido - o código não está no virtualenv ou pip.Fechando este problema, já que não é um problema de virtualenv (você pode obter o mesmo efeito instalando um interpretador Python completo em um nome de diretório longo) ..
Acabamos de encontrar esse problema.
Por que não usar o python do PATH? virtualenv já adiciona o diretório bin.
#!/usr/bin/env python
virtualenv já adiciona o diretório bin
Somente se você ativar o virtualenv. Virtualenv suporta ser usado sem ativação.
Se alguém achar isso confuso:
Uma solução alternativa para esse problema é não executar o pip diretamente, mas executar o interpretador python do virtualenv e passar o script pip para o python como a fonte a ser executada.
Isso significa que em vez de pip install -r requirements.txt
faça python -m pip install -r requirements.txt
Comentários muito úteis
Se alguém achar isso confuso:
Isso significa que em vez de
pip install -r requirements.txt
façapython -m pip install -r requirements.txt