Pip: Padrão para --user

Criado em 21 mar. 2014  ·  170Comentários  ·  Fonte: pypa/pip

Quando o pip é instalado em um sistema que possui uma instalação do SO Python, há atualmente um problema em que pip install foo gerará um erro porque não possui permissões de arquivo. Isso faz com que as pessoas executem sudo pip install foo que instala globalmente no sistema Python. Isso cria um problema em que as pessoas estão usando o pip para gerenciar pacotes no nível do sistema quando provavelmente deveriam estar usando o gerenciador de pacotes do sistema.

Portanto, minha intenção é que o pip seja padronizado para --user, no entanto, existem alguns pontos de discórdia com isso:

  • Como isso interage com o Windows? Isso faz sentido aí?
  • Como isso interage com Pythons altinstall'd? Especialmente aqueles instalados com ferramentas como https://github.com/yyuu/pyenv
  • O que fazemos quando as pessoas invocam o pip como root? Instalar em /root/.local/ não parece muito útil.
  • O que isso significa para get-pip e as instruções de instalação do pypa ?
  • ~/.local/bin não está no $PATH de muitas pessoas, há algo que possa ser feito sobre isso?
  • --user instalações não têm precedência para pacotes globais easy_install 'd, o que pode ser bastante inesperado.

Há uma série de questões que são relevantes aqui: #624 #1443 #1153 #1500 #1051

/cc @ncoghlan

user scheme auto-locked enhancement

Comentários muito úteis

Eu sonhei à noite com a opção --user se tornando o padrão (sem brincadeira), alguma chance de meus sonhos se tornarem realidade em breve?

Todos 170 comentários

O que isso significa para as instruções de instalação do pypa?

atualmente, a menção de acesso root ou Administrador está em uma nota de rodapé, então as instruções permaneceriam fundamentalmente as mesmas (assumindo que get-pip automaticamente padronizado para --user também). a mudança seria explicar que eles acabarão com instalações que se aplicam apenas ao usuário atual.

independentemente da mudança --user , as instruções atuais precisam explicar que algumas distribuições como o debian estão desabilitando o Ensurepip, então elas não devem procurar por isso como uma maneira de obter o pip.

A longo prazo, tenho certeza de que eles vão mantê-lo ativado, eles estão apenas descobrindo como fazê-lo.

embora esse problema seja descrito como sobre onde o pip deve gerenciar os pacotes por padrão, quase mais importante (pelo menos para mim) é que isso é indiretamente sobre onde get-pip colocará o pip por padrão.

Como isso interage com Pythons altinstall'd?
Especialmente aqueles instalados com ferramentas como https://github.com/yyuu/pyenv

o esquema do usuário é .local/lib/pythonX.Y/site-packages , então se você estiver gerenciando vários pythons com a mesma versão principal/secundária, você pode acabar com uma bagunça, eu acho.

para ferramentas como essa, que gerenciam pythons reais, fixar o pip no modo global faria sentido para eles.

Um problema relevante no rastreador de bugs redhat/fedora https://bugzilla.redhat.com/show_bug.cgi?id=662034#c10

Parece que para o Fedora/RedHat PATH=$PATH:$HOME/.local/bin:$HOME/bin já está em seu /etc/skel/.bash_profile . Isso faria com que as coisas instaladas com --user ainda aparecessem por padrão, pelo menos para usuários do bash (shell padrão). Talvez outras distros já tenham isso?

Não há nada especialmente diferente sobre o Windows que eu conheça. Mas acabamos de colocar o diretório padrão do Python no PATH das pessoas, não espero que obter um diretório de scripts por usuário seja particularmente fácil - e também pode haver dificuldades técnicas, não tenho certeza colocar uma variável de ambiente de nível de usuário como %LOCALAPPDATA% no nível de sistema %PATH% até funciona :-(

Eu sou contra apressar isso. Prefiro esperar até que tenhamos mais experiência com instalações de usuários e tenhamos conseguido resolver os problemas primeiro. Eu sei que é um problema da galinha e do ovo, mas não vejo a pressa em mudar como uma ajuda.

Além disso, com meu chapéu do Windows, eu tenho que dizer que tornar mais difícil para os usuários do Unix que ainda não descobriram que o uso descuidado do sudo é ruim para fazer coisas estúpidas, não é uma justificativa tão boa. .

Estou assumindo que isso só se aplicaria ao executar o pip de um sistema Python.

Bem, a coisa diferente no Windows é que não há um sistema fornecido pelo Python como existe no * nix que também vem com pacotes Python fornecidos pelo sistema :)

Eu particularmente não estou querendo apressar isso também. Eu só queria começar a discussão.

Isso realmente não afeta as pessoas que digitam sudo pip install , pois acho que instalar algo como root ainda deve ir para os pacotes do site do sistema por padrão. Isso seria para orientar as pessoas a usar --user ao executar como um usuário sem privilégios. No momento, o que você obtém é que pip install como um usuário comum simplesmente explode com um erro de permissão. Mesmo se melhorarmos essa mensagem para explodir e sugerir --user , isso ainda não é o melhor UX.

Ao falar com uma das pessoas do Fedora, acho que a maneira que pode fazer para fazer isso é implementar uma verificação de permissões. Se eu tiver permissão para gravar no diretório de pacotes do site, sou um usuário privilegiado e o pip instala no Python global, se não tiver, sou um usuário sem privilégios e ele instala em --user .

No que diz respeito ao Windows, geralmente evitamos o problema porque instalamos o Python em um diretório não privilegiado por padrão, portanto, o pip não aciona o UAC ao instalar globalmente. Se alguém alterar isso para instalar em Arquivos de Programas, o UAC será acionado quando executar o pip (o que também está OK). Não tenho certeza do que acontece se eles selecionarem uma instalação por usuário no instalador.

Como Paul observa, o PATH no Windows ainda não inclui o diretório de scripts _user_ (apenas o global), então definitivamente vale a pena levar em consideração.

No entanto, não vejo grandes barreiras no lado POSIX. Como essa ideia de UX soa: para instalações baseadas em rodas, verifique as permissões no diretório de destino da instalação e, se o usuário não tiver permissões de gravação, coloque um prompt perguntando se eles gostariam de fazer uma instalação --user ? Um novo sinalizador "--global" ou "--system" forçaria a resposta "não".

E então, em algum momento no futuro, poderíamos pular o prompt e simplesmente assumir --user se as permissões não fossem corretas para uma instalação global.

Um prompt (exceto no caso de --no-input) provavelmente faz sentido para a etapa de transição. Eu acho que a verificação de permissões deve fazer as coisas funcionarem para o Windows também, já que, por padrão, o local está em um local onde as pessoas têm permissões e, portanto, a única vez que eles acertariam isso seria se estivessem usando um administrador de sistemas fornecido pelo Python que explicitamente não t dar-lhes permissão.

Essencialmente, isso torna nosso modo de falha muito melhor.

tornando mais difícil para os usuários do Unix que ainda não trabalharam com o uso descuidado do sudo
é ruim fazer coisas estúpidas, não é uma justificativa tão boa assim..

sudo e segurança é realmente uma questão secundária IMO.
trata-se principalmente de evitar o conflito entre o empacotamento do sistema operacional e o pip no python do sistema.
Atualmente, os usuários do Linux são frequentemente colocados em uma situação impossível.

  1. Mandato do SO: 'Use o gerenciador de pacotes do SO; Não infecte seu sistema com pacotes instalados no roque pip (incluindo um get-pip 'd pip)'
  2. Realidade: "Os pacotes do SO (incluindo o pip) são muito antigos, e não posso atualizar para a versão experimental da distro, apenas para obter atualizações de algum pacote. Estou ficando desonesto...."

outro pequeno passo é documentar (assumindo que testamos) que você pode get-pip.py --user , e fazer com que o PUG mencione --user como uma possibilidade para a instalação de virtualenv (e wheel e twine também, se não estiver em um virtualenv)

FWIW, os fornecedores de distribuição também consideram o status quo um problema e estão procurando várias maneiras de melhorar as ferramentas para fazer atualizações seletivas sem afetar os componentes principais do sistema operacional. Ainda vale a pena abordarmos do lado upstream, já que esses esforços estão em vários estágios de maturidade e queremos uma solução consistente de plataforma cruzada para usuários finais.

Não tenho nenhum problema em mudar as coisas para ajudar a cooperar com distros no Unix; se o padrão para --user no Unix e não no Windows for aceitável, tudo bem para mim. Eu simplesmente não vejo a mudança de uma experiência ruim no Unix para uma experiência ruim no Windows como uma boa troca. E ainda não estou convencido de que --user no Windows está pronto para o horário nobre.

Observe que acionar o UAC ao executar o pip _é_ ruim no Windows, porque o que realmente significa é que o pip não será executado, exceto em uma janela de console elevada. Isso não significa que os usuários do pip recebam um bom prompt para o qual eles possam dizer "OK", infelizmente, é assim que os aplicativos GUI funcionam ...

@pfmoore Qual você acha que deve ser a experiência do usuário do Windows quando você pip install algo e não tem permissões para gravar no diretório?

FWIW Estou totalmente OK em tornar isso opcional dependendo do Windows ou não. Eu só estou querendo saber se a verificação de "Tenho permissões para gravar na pasta de pacotes do site" não alcançará isso de qualquer maneira em 99% das instalações, e se instalar em --user seria uma experiência melhor no fração de casos em que você não tem permissões de gravação no diretório de pacotes do site.

Em outras palavras, se verificarmos as permissões, a proposta não está substituindo a instalação global por uma instalação do usuário, está substituindo um erro de permissão por uma instalação --user .

a proposta não está substituindo a instalação global por uma instalação do usuário
está substituindo um erro de permissão por uma instalação --user

ok, mas lembre-se de que a ideia de verificação de permissões (#1048) não será a coisa mais fácil

Será bem fácil no caso Wheel, e podemos cobrir o caso de 99,9% com sdists, só deve ser um problema em setup.py's que fazem coisas realmente estranhas.

Qual você acha que deve ser a experiência do usuário do Windows quando você instala algo pip e não tem permissões para gravar no diretório?

Bem, ser capaz de gravar no diretório de pacotes do site é tão raro no Windows que não tenho certeza de quão relevante é a questão na prática. Mas se isso acontecesse, eu diria que um erro dizendo "system site-packages não é gravável - você pretendia usar --user ?" seria a abordagem sensata.

Na verdade, acho que seria melhor no Unix também. Mudar o comportamento dependendo da capacidade de escrita é bizarro, e não está claro para mim se usar --user para um Python construído pessoalmente em um diretório gravável é a abordagem correta (mas eu tenho precisamente zero experiência de tal configuração, então Eu não tenho nada para apoiar essa opinião).

Sugestão: Comece com um erro sugerindo --user como acima. Quando as pessoas estiverem usando --user com mais frequência e tivermos mais experiência com isso, vamos considerar mudar o padrão.

A abordagem que Paul sugere é mais ou menos o que eu tinha em mente, mas com um prompt sim/não, em vez de sair com uma mensagem de erro. Existem prós e contras para essas duas abordagens (principalmente relacionadas a como elas falham quando invocadas de outro script).

Seria possível adicionar ao Python algo como sys.localprefix (eu vejo python-dev aqui)?
Sys.localprefix seria o padrão para sys.prefix. As distribuições podem defini-lo da mesma forma que definem o prefixo (por exemplo, prefix = '/usr', localprefix='/usr/local'). Pip e easy_install usariam sys.localprefix como um local para instalar se usado como sudo, se eles não tiverem direitos suficientes, volte para --user.

Fizemos algo assim com "instalação de gem" no Fedora 17 e os desenvolvedores do Ruby geralmente ficaram muito satisfeitos com isso, então pensei em compartilhar:

  • "gem install foo" instala "foo" em ~/somedir if uid != 0
  • "gem install foo" instala "foo" em /usr/local/somedir se uid == 0
  • "yum install rubygem-foo" instala "foo" empacotado em RPM em /usr/somedir

Acho que escolher o diretório de instalação com base nos privilégios do usuário seria muito confuso para as pessoas; "pip install foo" deve funcionar da mesma maneira para todos os usuários não root. Se você considerar a maioria dos usuários, eles vão querer "pip install" em sua casa e "sudo pip install" em um diretório de todo o sistema. Portanto, acho que é a melhor abordagem fazer isso com base no uid, como mostrado acima - e para aqueles usuários que não são root, mas desejam instalar em um diretório de todo o sistema, sempre há a opção --target .

@bkabrda é uma escolha fácil de fazer, desde que você não esteja preocupado em adicionar scripts ao $PATH. O que você fez lá?

@Ivoz como observado por @dstufft , o Fedora já tem $HOME/.local/bin no PATH, então tudo funcionou fora da caixa (falando de scripts).

A sugestão de Slavek me parece boa para sistemas POSIX. Ele também deve funcionar bem com contêineres, já que as coisas que estão sendo executadas em um contêiner podem ser instruídas a pensar que é uid 0, mesmo que seja algo totalmente diferente de fora do contêiner.

Para o Windows, tenho menos certeza de qual é a resposta certa. Não temos o mesmo problema em entrar em uma discussão com o gerenciador de pacotes do sistema, embora exista até certo ponto (instalação pip vs instaladores MSI) e tenha a complicação adicional de que, mesmo no Python 3.4, o PATH opcional do instalador modificações apenas adicionam o diretório global de Scripts, não o diretório por usuário.

O Windows também tem estranheza com base em se o Python está instalado no local padrão (não controlado) ou em Arquivos de Programas (escalonamento de privilégios UAC necessário para fazer alterações).

A ideia de "localprefix" sugerida por @rkuska parece legal para mim, simples e fácil. Também gosto muito da abordagem que o @bkabrda sugere, especialmente para distros como o Arch que tornam o python 3.x o python padrão.

Mais uma observação é que o Arch desativou o assurancepip na versão 3.4.0 assim como o Debian (principalmente porque queremos fornecer as versões mais recentes de setuptools e pip, enquanto as versões empacotadas podem estar desatualizadas por muito tempo), então seria bom ter uma dica para isso.

@lvoz
Para o Arch, não adicionamos nenhum caminho em $HOME to PATH, mas ainda acho bom. Já temos uma entrada wiki para Ruby que diz ao usuário para adicioná-la.

Seria bom se, em vez de apenas desativá-lo, os desenvolvedores do Arch e do Debian ajudassem Slavek a trabalhar em seu patch para garantir que o pip reconstruísse uma roda das versões do sistema e instalasse isso em ambientes virtuais.

Apenas para sua informação, já temos compilações Python 3.4 RPM em funcionamento no sistema de compilação Copr do Fedora (testando, não é aconselhável instalá-las se você não quiser quebrar nada). Se você quiser saber mais sobre como abordamos isso, dê uma olhada no código etc, veja minha discussão com Barry Warsaw [2] no debian-python ML.
(Nossos patches ainda precisam de um pouco de amor antes de propô-los a montante, mas tudo funciona bem para nós ATM a jusante)

[1] http://copr-fe.cloud.fedoraproject.org/coprs/bkabrda/python-3.4/
[2] https://lists.debian.org/debian-python/2014/03/msg00046.html

Desculpe, mas o AFAIK Arch nunca suportou wheel, nem queremos fazer com que o gerenciador de pacotes de invocação de garantia pip (me corrija se eu entendi errado essa abordagem).

Para o Ensurepip, seria uma boa ideia avisar o usuário para não instalar o pip usando o Ensurepip, e isso é o máximo que consigo pensar por enquanto.

Nosso surepip nunca invocará o gerenciador de pacotes. Resumindo, o surepip do Fedora dependerá das ferramentas de configuração e do pip empacotados do sistema para estarem sempre presentes (nosso pacote python3 dependerá deles, o que criará um loop de dependência, mas podemos lidar com isso) e quando o usuário criar um novo virtualenv, ele reempacotará ferramentas de configuração do sistema e pip em rodas e instalá-los no novo virtualenv.
Estamos começando a ficar um pouco fora do assunto, então acho que devemos continuar essa discussão em outro lugar...

@felixonmars Isso significa que no Arch venv está quebrado da mesma forma que no Debian?

Ok, obrigado pela explicação, acho que entendi a ideia. Vou ver o que posso fazer e acompanhar o debian-python para isso.

@dstufft Sim, a versão do pacote foi instalada em vez da versão do sistema.

@bkabrda Então, isso resolve o problema se você estiver invocando o pip com um sistema Python, temos um caso especial virtualenv/venv nesse caso (que não é o fim do mundo). Mas também significa que estamos assumindo que todos os Pythons são Pythons do sistema, mesmo aqueles instalados pelo usuário em seu homedir, como https://github.com/yyuu/pyenv (que é como eu executo o Python na verdade). Então não tenho certeza, por isso pensei na verificação de permissão.

idem o que @dstufft disse, ao usar uma ferramenta como pyenv para manipular pythons não-raiz, seria muito estranho root ser a chave para fazer uma instalação global (onde "global" != "sistema")

Fizemos algo assim com "gem install" no Fedora 17

você quer dizer que o rpm do gem para o fedora 17 tem isso como um hack de distro?, ou o próprio gem tem essa lógica?

um pensamento é que o pip deve fornecer um "modo amigável ao sistema" que pode ser ativado por distros que estão empacotando pip, ou quando os usuários sabem que estão instalando o pip em um python gerenciado pelo sistema. caso contrário, o pip faz sua lógica global por padrão normal.

Ah @felixonmars acabei de ver https://projects.archlinux.org/svntogit/packages.git/tree/trunk/PKGBUILD?h=packages/python , se tudo o que você está fazendo é chamar --without-ensurepip tudo bem . Isso deixa o módulo assurancepip intacto para o módulo venv. Os patches que o Ubuntu (Debian?) tem atualmente na verdade chamam rm -rf no próprio pacote assurancepip, tornando-o indisponível para ser chamado dentro de um venv.

Acho que o padrão para instalações de usuário foi proposto por Nick há dois anos, ou talvez outra pessoa há mais tempo, mas a discussão foi em muitas direções e não foi frutífera. O principal obstáculo era a compatibilidade com o IIRC, mas atualmente os administradores de sistemas e usuários do pip podem estar mais acostumados a ter cuidado com as atualizações do virtualenv/pip/setuptools, para melhor ou para pior. Não me lembro se essa discussão aconteceu em distutils-sig ou pypa-dev.

@dstufft Ah, entendo... Mas ainda me sinto errado em ter uma versão empacotada (talvez antiga) instalada enquanto há pacotes instalados no sistema :)

@felixonmars bem, o problema é que você não pode instalar um pacote do sistema em um virtualenv afaik :) (E mesmo que pudesse, existem preocupações diferentes com o que você deseja em um pacote do sistema versus dentro de um virtualenv)

@dstufft É aí que o rewheel de Slavek entra em ação, mas isso é um pouco fora do tópico :)

@dstufft Obrigado!

Não tenho certeza se devo continuar a discussão lá, porque isso não deve ser um problema, já que não separamos o pip no Arch, e o rewheel deve gerar uma roda utilizável :)

@dstufft você está certo de que provavelmente precisaríamos especializar virtualenv e possivelmente até pyenv, o que parece feio. Eu tenho que admitir que não estou familiarizado com o pyenv, então não consigo pensar em nenhuma solução "adequada" para isso agora. Vou tentar dar uma olhada mais de perto e pensar em algo.

@qwcode para "gem install" no Fedora, é um patch downstream. TBH Eu não toquei no Rubygems do Fedora por muito tempo, mas da última vez que verifiquei, era apenas downstream.

Eu postei um link para este problema para bug relacionado em python [1]. Eu gostaria de mover esta discussão para o núcleo python, para ter um local configurável para instalações locais de não apenas pip mas também easy_install e python setup.py install , depois que o pip poderia usar ( por exemplo) sys.localprefix dir se uid==0 e instalar no diretório do usuário se uid!=0 como @bkabrda mencionou.

Por enquanto, estou bem com a instalação do pip no diretório do usuário por padrão.

[1] http://bugs.python.org/issue1298835

Como Nick apontou, mudei a discussão de issue1298835 para pypa-dev [1].
[1] https://groups.google.com/forum/#!topic/pypa -dev/r6qsAmJl9t0

Padrão para --user

Boa ideia!

pip install foo lançará um erro porque não tem permissões de arquivo. Isso faz com que as pessoas executem sudo pip install foo que instala globalmente no sistema Python

É pior do que isso. Muitas pessoas (como usuários de uma rede de computadores de uma universidade) não têm privilégios sudo. Quando o pip falha com um erro de permissão, eles:

  1. Envie um e-mail para o administrador e peça para instalar o pacote. Isso é lento e tedioso para todos.
  2. Desista e faça sem o pacote.

Somente se forem particularmente experientes ou bem informados tentarão pip install --user .

Se acabarmos decidindo contra 'padrão para --user', devemos considerar as alternativas menos disruptivas:

  1. Fallback para --user (se a instalação falhar devido a erros de permissões)
  2. (Se a instalação falhar devido a erros de permissão), incentive o usuário (em letras grandes e amigáveis) a tentar --user

Na verdade, tenho usado --user em todas as minhas instalações há algum tempo, mas geralmente as pessoas não estão cientes dessa opção. Concordo que é irritante ver o erro de permissão toda vez que você esquece a opção. Percebi que as instalações do usuário não são compatíveis com o conda (conda/conda#448).

Eu gostaria de reviver isso, pois as pessoas vão encontrá-lo no Windows com muito mais frequência agora que o padrão 3.5 é instalar em Arquivos de Programas (o que requer privilégios de administrador para modificar).

Eu gosto da opção "fallback to --user on permission error" melhor para instalações, com "padrão para --user e fallback to system" em desinstalações e talvez adicionar uma opção --system ou --system-only para evitar o recuo. Os usuários que executam deliberadamente o pip com permissões de administrador obterão uma instalação do sistema conforme o esperado e, atualmente, os usuários sem permissões receberiam um erro, portanto, não acredito que haja problemas de compatibilidade aqui.

Meu objetivo é que um usuário desinformado possa fazer pip install spam; python -c "import spam" sem erros (embora possivelmente um aviso ao tentar novamente com --user ).

Eu tenho pensado nisso ultimamente, especialmente desde que #2403 e #2401 foram abertos recentemente, o que me fez pensar sobre o uso de sudo pip install e como isso pode quebrar sistemas fora apenas dos problemas de permissões.

Para este fim, eu me pergunto se o melhor objetivo final não é apenas --user ser o padrão, sem verificações de permissões mágicas e adicionar um novo sinalizador como --global , --system , ou --no-user que irá restaurar o comportamento anterior. Isso é mais fácil de explicar para as pessoas, pois terá o mesmo comportamento, não importa como/onde as coisas estejam instaladas.

Agora, se decidirmos que esse é o caminho que queremos seguir, ainda há o problema de como chegamos a esse ponto a partir de onde estamos hoje. Obviamente, em qualquer ponto em que mudarmos o padrão, será uma mudança de ruptura bastante grande, então precisaremos de um tempo de espera bastante longo. Acho que, se decidirmos seguir esse caminho, a melhor maneira de fazer isso seria continuar mantendo a opção --user , adicionar uma nova opção como --global e, se uma ou a outra opção não estiver configurada, faça a mágica de verificação de permissão da qual falamos e se a mágica decidiu usar o comportamento --global , emitiremos um aviso de depreciação muito alto. Esse aviso de descontinuação permaneceria por muito mais tempo do que nossas outras descontinuações que emitimos, pois seria uma mudança bastante importante no comportamento. Acho que também gostaríamos de adicionar uma opção que desative o fallback mágico e implemente o comportamento futuro para que as pessoas possam ter esse comportamento hoje.

Outra questão importante é o que devemos fazer se detectarmos que o Python no qual estamos instalando não possui sites de usuários habilitados. Nesse caso, eu simplesmente declararia que --user é um erro e, para esses Pythons, simplesmente retornaremos ao padrão --global . Isso cobriria o virtualenv/venv acredito que automaticamente, e se alguém quiser um ambiente isolado de peso "mais pesado" usando Pythons totalmente compilados, eles podem simplesmente corrigir site.py para que eles definam ENABLE_USER_SITE para False no topo do arquivo.

+1, e eu votaria em --system.

Vou notar, e tenho certeza que você vai adorar isso, o padrão do Ubuntu mudou:

https://launchpad.net/ubuntu/+source/python-pip/1.5.6-4ubuntu1

Em 09 de fevereiro de 2015, às 16h41, Donald Stufft escreveu:

Para este fim eu me pergunto se o melhor objetivo final não é apenas que --user é o
padrão, sem verificações de permissões mágicas e adicione um novo sinalizador como --global ,
--system , ou --no-user que irá restaurar o comportamento anterior. este
é mais fácil de explicar às pessoas, pois terá o mesmo comportamento, não importa
como/onde as coisas são instaladas.

Eu acho que --system está errado porque isso realmente só se aplica a alguns Pythons. Não se aplica a:

  • Python no Windows
  • Pythons instalados pyenv
  • Conda instalado Pythons
  • Nix Pythons Instalados
  • Pythons compilados personalizados.

Ele se aplica _somente_ em sistemas *nix onde o Python é enviado pelo sistema. Eu sinto que --global é um nome muito melhor para essa bandeira.

E FML, por que o Debian/Ubuntu sente a necessidade de adicionar constantemente patches aleatórios que quebram os casos de uso esperados?

Então, se o patch do Ubuntu for revertido, qual é a linha do tempo disso sendo corrigida aqui? Uma semana/um mês/3 meses/6 meses/um ano...?

Depende do que você quer dizer com fixo.

Supondo por um momento que estamos usando a ideia que eu tive 2 posts atrás (que ainda precisa de aprovação dos outros desenvolvedores de pip), provavelmente poderíamos obter rapidamente o plano de transição onde o seguinte é verdadeiro:

  • Quando --user é passado, _sempre_ instalamos nos pacotes do site do usuário.
  • Quando --global (ou o que for) é passado, _sempre_ instalamos nos pacotes globais do site.
  • Quando nenhum é passado, implementamos um método de fallback que:

    • Detecta se estamos em um ambiente virtual e em caso afirmativo age como se --global fosse passado.

    • Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se --global fosse passado.

    • Detecta se o usuário efetivo não tem permissões de gravação para sys.path , e se ele não age como se --user fosse passado.

    • Finalmente, se todos os outros métodos de detecção falharem, aja como se --global fosse passado e imprima um aviso de descontinuação dizendo que em algum momento no futuro o comportamento disso mudará e, em vez disso, será instalado em --user .

Isso não impedirá alguém de fazer sudo pip install foo em seu sistema Python, no entanto, imprimirá um aviso de que em algum momento isso significará --user e dirá a eles para começarem explicitamente a usar --global . Uma vez que o acima foi lançado por um tempo suficiente, poderíamos remover o caminho de código obsoleto e simplificar isso para que seja simplesmente:

  • Quando --user é passado, _sempre_ instalamos nos pacotes do site do usuário.
  • Quando --global (ou o que for) é passado, _sempre_ instalamos nos pacotes globais do site.
  • Quando nenhuma opção é passada, implementamos um método de fallback que:

    • Detecta se estamos em um ambiente virtual e se estiver, age como se --global fosse passado.

    • Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se --global fosse passado.

    • Finalmente usa --user como padrão.

No entanto, passar do primeiro comportamento para o segundo comportamento terá uma linha de tempo bastante longa. Essa será uma mudança realmente importante, que quebrará as coisas para qualquer software (como sal, chef, fantoche) ou script de implantação (como scripts personalizados do Fabric integrados em milhares de projetos em todo o mundo) que espera que sudo pip install <foo> será instalado no Python global. Precisaremos dar um longo tempo de espera para que as pessoas vejam o aviso e modifiquem seus softwares e scripts para passar um sinalizador --global explícito se realmente precisarem desse comportamento.

Acho que o plano sugerido por Donald é bom, embora se a equipe do pip decidir adotar essa abordagem, também devemos registrar um problema de bloqueador de versão 3.5 com o CPython para obter o diretório de scripts por usuário adicionado ao caminho no Windows junto com o global 1. Se o 3.5 adicionar isso junto com a mudança para a instalação em Arquivos de Programas por padrão, devemos obter o comportamento desejado de instalar sem permissões de administrador, continuando a "simplesmente funcionar".

Ser capaz de alterar o local de instalação padrão por meio dos arquivos de configuração do pip também pode ser útil, permitindo que as pessoas optem por "por usuário por padrão" em seus próprios sistemas, mesmo que o padrão ainda não tenha sido alterado. (por exemplo, "default-install=usuário" vs "default-install=global")

@dstufft : Fico feliz em dar uma mão para implementar sua proposta conforme informado no bug do ubuntu, se você precisar de mim. Assim que obtivermos esse comportamento no tronco, farei o backport e substituirei o patch atual do ubuntu por este, é claro.

Mantenha-me informado se precisar de ajuda.

Estou +1 no plano de @dstufft . Eu iria para --global como o nome, pelas razões indicadas. Já estamos sentados em cima do muro há muito tempo, vamos em frente.

O'n e +1 na sugestão do @ncoghlan de que o Python 3.5 adicione o diretório do site do usuário ao PATH no Windows. Vamos evitar mais obstáculos para essa transição.

Também sou +1 para o plano de @dstufft e +1 para --global , embora ainda esteja pensando sobre o sudo pip install foo precisando --global . Existe, de fato, alguma necessidade de o root ter pacotes de sites do usuário? Poderíamos fazer um caso especial de root para ter os pacotes do site desativados por padrão? (O que faria sudo pip install foo funcionar exatamente como agora)

Eu nunca vi ninguém usando --user para root com o estado atual, mas se alguém realmente conhece esse caso de uso, eu gostaria de saber.

Um pensamento que me ocorreu é como o diretório do site do usuário funcionará com várias versões do Python instaladas?

Se eu fizer pip install pytest --user no Python 2.7 e 3.4 (com o Python 3.4 meu Python padrão), qual versão o comando py.test será executado? Eu tenho uma suspeita de que as duas instalações se sobrescreverão, então é uma situação de "o último vence", o que _não_ é bom. Além disso, se for "o último vence", e eu instalar a versão 2.7 após a 3.4, como eu corrigiria isso para tornar a 3.4 o padrão novamente?

E as desinstalações? Considere o seguinte cenário (não testado, porque eu precisaria configurar uma máquina limpa se não quisesse arriscar quebrar meu laptop principal):

    C:\Apps\Python34\python.exe -m pip install pytest --user
    C:\Apps\Python27\python.exe -m pip install pytest --user
    C:\Apps\Python34\python.exe -m pip uninstall -y pytest

Primeiro, por que o segundo comando não emitiu um aviso de que estava substituindo um arquivo existente? Ou seria? Se foi ou não, tenho alguma opção sobre o que fazer?

Segundo, a desinstalação não falharia porque a soma de verificação de py.test.exe não corresponderia ao valor no arquivo RECORD ? Se falhar, como faço para desinstalar? Se não falhar, quebrará minha cópia do Python 2.7 do pytest (excluindo o exe)?

E finalmente (por enquanto!) o diretório de scripts do usuário iria antes ou depois do diretório de scripts do sistema em PATH? IMO, ele deve ir depois, caso contrário, uma instalação do usuário de um pacote em um Python que _não_ foi solicitado pelo usuário para ser "o Python padrão" poderia substituir o mesmo pacote instalado nos pacotes de site do sistema "padrão" do Python.

Hmm, talvez haja algumas questões em aberto que precisam ser resolvidas antes de fazermos essa mudança...

Eu esperaria que os conflitos de nome no diretório de script de usuário compartilhado do Windows fossem tratados da mesma maneira que são tratados em sistemas POSIX com seus diretórios bin compartilhados: o Python 3 não instalaria o nome de script não qualificado para pacotes instalados, portanto, o não qualificado name se referiria à versão do Python 2.

O mesmo vale para se a instalação do sistema ou a instalação por usuário tem precedência por padrão: coloque o diretório do script do usuário após o do sistema.

"Python 3 não instalaria o nome de script não qualificado para pacotes instalados" - presumivelmente você quer dizer que pip e setuptools (em Python 3) não, aqui? Então, isso é uma mudança para essas ferramentas?

Ah, e blz. Minha memória muscular é 100% treinada para digitar "pip install foo" para instalar no meu Python padrão (3.4). Isso vai ser um inferno para treinar novamente.

Além disso, os usuários do Windows podem escolher se "python" significa Python 2 ou 3 (via "tornar este o Python padrão" e "Adicionar ao PATH") - ao contrário dos usuários do Unix, onde o sistema Python faz as regras. Então, se eu disser que quero tornar o Python 3.5 meu padrão, por que "pip" (ou qualquer outro nome não qualificado) não deveria se referir a essa versão? Parece bizarro que um usuário com apenas o Python 3.5 instalado no Windows não possa usar nomes não qualificados simplesmente por causa de um problema do Unix sobre como o sistema Python precisa de coisas nomeadas. (Desculpe se minha descrição das restrições do Unix for imprecisa - eu realmente não entendo o problema). As pessoas que instalam várias versões do Python precisam de uma solução, mas essa solução não deve afetar a maioria que precisa apenas de uma versão.

Talvez a resposta mais simples seja que o diretório de scripts do usuário deve ser versionado, assim como o diretório de pacotes do site do usuário é?

Ah, e esse debate deve ser no python-dev e não aqui, já que é mais geral sobre o diretório do site do usuário?

Reabrir a discussão de design do PEP 370 para o diretório de scripts por usuário do Windows em python-dev certamente seria razoável. É estranho que as instalações de scripts globais no Windows tenham o escopo da versão do Python, mas as instalações de scripts por usuário não.

Isso contrasta com a situação no POSIX, que usa consistentemente um namespace compartilhado para executáveis ​​em ambos os níveis (global ou por usuário), portanto, é mais provável que conflitos de nome apareçam no momento da instalação, em vez de sombreamento de nome em tempo de execução.

No que diz respeito à solução geral para lidar com a instalação paralela, essa seria a opção "-m" - dessa forma, você sempre sabe qual Python está invocando, em vez de adivinhar o conteúdo de uma linha shebang de um script separado.

Entendido sobre -m , mas da última vez que foi mencionado no contexto de como documentar as coisas, a forte preferência era que deveríamos tratar pip install foo como a maneira canônica de instalar as coisas (com -m e comandos versionados sendo tratados como exceções para casos especializados.

O manual do pip nem sequer _menciona_ alternativas (exceto no caso de usar -m para atualizar o próprio pip no Windows).

Eu recomendo -m nos documentos do pacote stdlib para lidar com a invocação de pip quando
lidar com instalações paralelas do Python - é o único estilo de invocação que
funciona em todas as plataformas, para instalações globais, instalações de usuário e virtual
ambientes.

Em 09 de fevereiro de 2015, às 19h58, ncoghlan escreveu:

Ser capaz de alterar o local de instalação padrão por meio dos arquivos de configuração do pip
também pode ser útil, permitindo que as pessoas optem por "por usuário por padrão" em
seus próprios sistemas, mesmo que o padrão não tenha mudado
ainda. (por exemplo, "default-install=usuário" vs "default-install=global")

Eu gosto deste. Uma das coisas com as quais estamos lutando é como resolver
abordagem mais conservadora do upstream para migrar para um padrão --user, com
distros objetivos concorrentes de tornar o sistema pip seguro e consistente com outros
Ferramentas. Por exemplo

https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1419695
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=725848

Se tivéssemos um arquivo de configuração de todo o sistema para selecionar o padrão, em
pelo menos todo o maquinário envolvido seria idêntico, e as distribuições não
tem que carregar deltas feios. Tudo o que teríamos que fazer seria mudar o
config e documente isso para nossos usuários. Os problemas causados ​​seriam
nosso para lidar, mas pelo menos seria fácil de explicar.

Eu não acho que o Debuntu atualmente instala um arquivo pip.conf em todo o site (terei
para verificar novamente).

https://pip.pypa.io/en/latest/user_guide.html#configuration

Uma complicação: instalamos diferentes scripts pip para Python 2 e Python 3,
então acho que precisaríamos de arquivos de configuração separados para as diferentes versões do
Python, por exemplo, /etc/{xdg/pip/}/pip{2,3}.conf ou algo parecido.

Em 10 de fevereiro de 2015, às 01h24, Paul Moore escreveu:

Um pensamento que me ocorreu é como o diretório do site do usuário funcionará com
várias versões do Python instaladas?

No Debian/Ubuntu (talvez todos os *nixes?) não temos colisão porque o
bibliotecas são instaladas em ~/.local/lib/pythonX.Y/site-packages

Nós _do_ obtemos colisões em ~/.local/bin. Instalando um pacote com um
script 'foo' usando pip install --user foo e pip3 install --user foo will
acabam sobrecarregando o script ~/.local/bin/foo.

Uma desvantagem dessa mudança é que acho que o Fedora é a única distribuição downstream que adiciona ~/.local/bin a $PATH por padrão (e deve vir antes de /usr/bin e /usr/local/bin apenas como os pacotes do site do usuário vem antes dos pacotes do site). Idealmente, os downstreams poderão modificar seus sistemas para que ~/.local/bin esteja em $PATH por padrão.

Em 10 de fevereiro de 2015, às 07:24, Donald Stufft escreveu:

Uma desvantagem dessa mudança é que acho que o Fedora é o único downstream
distro que adiciona ~/.local/bin a $PATH por padrão (e deve vir
antes de /usr/bin e /usr/local/bin assim como os pacotes do site do usuário vêm
antes dos pacotes do site). Idealmente, os downstreams poderão modificar seus
sistemas para que ~/.local/bin esteja em $PATH por padrão.

Sim, mas podemos tomar uma decisão separada sobre isso. (Ou melhor, a jusante
distros podem fazer isso.)

(e deve vir antes de /usr/bin e /usr/local/bin assim como o usuário
pacotes do site vem antes dos pacotes do site)

Hmm, @ncoghlan apenas disse o contrário, que (no Windows, nesse particular
context) o diretório de scripts do usuário deve ser _após_ o do sistema. Que
Eu concordo desde que o diretório de scripts do usuário não seja versionado. Se é
versionado, estou menos preocupado. Mas isso provavelmente reflete o fato de que
Os usuários do Windows nunca precisaram suportar scripts não versionados conflitantes e
monstruosidades como pip2/pip3, do jeito que os usuários do Unix têm ;-)

Ah, e a coisa do script clobbering é um problema mais geral que não está realmente relacionado a --user exatamente. O mesmo problema existe em todos os lugares, exceto nas instalações do Windows --global . Acho que a solução para esse problema é uma preocupação/problema secundário que devemos resolver separadamente a essa questão.

Então pensamentos atuais:

  • Acho que há um acordo sobre a ideia geral que postei anteriormente, então acho que vamos querer avançar com algo assim.
  • Vamos usar o sinalizador --global .
  • Provavelmente queremos algum tipo de aviso se estivermos instalando em --user e ~/.local/bin não estiver em $PATH .
  • Queremos algum tipo de opção default-install que essencialmente desabilitará o comportamento de fallback e apenas codificará para --global ou --user .
  • A partir do pip 6.0, temos arquivos de configuração específicos da máquina localizados em /etc/ mas não são específicos da versão do Python que está executando o pip. Eu acho que é um bom recurso, embora um pouco separado também (e pode andar de mãos dadas com a solução do problema de script clobbering também).

Ainda vejo uma grande questão em aberto: a longo prazo, o que queremos que aconteça quando alguém fizer sudo pip install foo ou melhor, se alguém tiver permissão para gravar no diretório site-packages ?

As opções que consigo pensar são:

  1. Instale em --global . Essa é a opção mais compatível com versões anteriores e provavelmente representa o que os usuários esperam quando digitam isso. No entanto, tem a desvantagem de (silenciosamente) mexer com o Python global, o que em muitos sistemas pode causar sistemas quebrados.
  2. Instale em --user , isso protegerá de sistemas quebrados (eu acho?) mas não acho que alguém esperaria que o usuário root fizesse uma instalação /root/.local/ .
  3. Apenas erro e exija que o usuário selecione --user ou --global manualmente.
  4. Escolha uma das duas primeiras opções, mas forneça uma opção que as distros possam ativar em /etc/ que habilitará a terceira opção.

A quarta opção pode ser a melhor, mas acho que devemos tentar selecionar uma das outras opções primeiro, se pudermos chegar a algum tipo de solução que funcione da mesma forma em todas as plataformas/cenários e faça sentido em todas elas. preferiria ter um comportamento consistente entre plataformas, se possível.

Eu sinto que a terceira opção é provavelmente ruim, já que "Eu tenho permissão de gravação" será o cenário em que qualquer pessoa no Windows está no pré-Python 3.5, ou qualquer pessoa que use Conda ou qualquer pessoa que use pyenv. Errar parece ser a coisa errada a se fazer em todos esses casos e é um pouco hostil ao usuário para inicializar.

Então, acho que entre 1 e 2 realmente se resume a quão ruim é a prática que achamos que é para as pessoas (conceitualmente) fazer sudo pip install --global foo . No Windows, Conda, pyenv, etc, sinto que a resposta é "não achamos que seja uma prática ruim". No * nix, sinto que talvez a resposta seja "os usuários devem ter permissão para fazer o que quiserem em seu sistema, mas devemos fornecer trilhos para afastá-los de coisas "ruins"".

Então, pensando mais sobre isso, acho que teria que escolher a primeira opção como a opção correta para nós. Isso resolve mais ou menos os problemas de compatibilidade com versões anteriores, já que o comportamento que realmente estaríamos mudando é que, se você digitar pip install foo sem permissão para instalar nesses diretórios globais, instalará em --user em vez de levantando um erro. Eu acho que é improvável que alguém esteja lá fora realmente dependendo do pip gerar um erro nesse caso. Eu também acho que pip install --user como usuário root é improvável que seja o que alguém espera ou quer e é realmente apenas uma arma para os usuários.

Então minha proposta atualizada seria:

  • Quando --user é passado, sempre instalamos nos pacotes do site do usuário.
  • Quando --global é passado, sempre instalamos nos pacotes globais do site.
  • Quando nenhum é passado, implementamos um método de fallback que:

    1. Detecta se estamos em um ambiente virtual e se estiver, age como se --global fosse passado.

    2. Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se --global fosse passado.

    3. Olha para default-install e, se existir, usa --user ou -global com base nele.

    4. Detecta se o usuário efetivo não tem permissões de gravação para pacotes de sites globais e se eles não agem como se --user fosse passado.

    5. Finalmente, se todos os outros métodos de detecção falharem, aja como se --global tivesse sido passado.

Isso significaria nenhum período de depreciação e que a expectativa é que, na ausência de --user ou --global , tentaremos fazer a melhor estimativa com base nos recursos do Python em que estamos executando , o usuário efetivo e qualquer método de instalação padrão configurado.

(e deve vir antes de /usr/bin e /usr/local/bin assim como o usuário
pacotes do site vem antes dos pacotes do site)

Hmm, @ncoghlan apenas disse o contrário, que (no Windows, nesse particular
context) o diretório de scripts do usuário deve ser _após_ o do sistema. Que
Eu concordo desde que o diretório de scripts do usuário não seja versionado. Se é
versionado, estou menos preocupado. Mas isso provavelmente reflete o fato de que
Os usuários do Windows nunca precisaram suportar scripts não versionados conflitantes e
monstruosidades como pip2/pip3, do jeito que os usuários do Unix têm ;-)

Eu nem estou pensando em termos de conflito de nomes de scripts. Eu só acho que é totalmente errado nossa variável $PATH agir de forma diferente do que sys.path . Até onde eu sei, a ordem sys.path é: stdlib > user site packages > global site packages. Eu acho que seria realmente confuso se a ordem some-script fosse global bin dir > user bin dir enquanto python -m some-script fosse user site packages > global site packages.

Se houver um problema com os diretórios de script (e versionados versus não versionados), acho que devemos corrigir esse problema, mas que não é super relevante para a ordem em que eles devem estar, porque sinto que qualquer outra coisa além de corresponder ao que sys.path faz é super errado.

Bom ponto, devemos assumir (e recomendar) que $PATH segue sys.path, com (em termos do Windows) C:PythonXY antes de %APPDATA%PythonXYScripts antes de C:PythonXYScripts. Vou observar isso no thread python-dev.

A última proposta de Donald parece boa para mim (igual à minha original mais todos os detalhes importantes que deixei de fora :) ). Concordo 100% com o parágrafo "Pensando mais nisso..." também.

Quanto à configuração do PATH no Windows, isso será quase impossível. Um instalador de todo o sistema só pode configurar variáveis ​​de ambiente de todo o sistema e não pode incluir expansões, portanto, você não pode definir caminhos diferentes para cada usuário. (O instalador por usuário pode fazer isso, mas nesse caso --global será bem-sucedido e, portanto, não há necessidade.)

Além disso, por causa do tratamento PATH quebrado do Windows, as configurações de todo o sistema _sempre_ superam as configurações por usuário. Isso levou à minha meia sugestão um tempo atrás (em python-dev, IIRC) sobre o uso do iniciador py.exe para scripts não versionados, para que pip.exe sempre fosse para o sistema ou usuário Python mais recente em vez do um que o instalou, e (por exemplo) pip.exe -3.5 permitiria a seleção de versão específica.

A única maneira de fazer isso realmente funcionar é que o instalador do Python comece a instalar arquivos em lote para configurar o PATH mediante solicitação (e talvez um atalho que execute o arquivo em lote). Então, a primeira coisa que os usuários digitariam é activate-py35 e então seu PATH está configurado corretamente para 3.5. Estou muito dividido com isso, pois não quero entrar na situação vcvarsall.bat, mas ao mesmo tempo será ótimo para scripts que atualmente fazem suposições sobre locais de instalação ou tentam passar pelo registro Para encontrar isso.

e talvez um atalho que execute o arquivo de lote

Na minha opinião, este é um atalho "Python 3.5 (32 bits) Command Prompt". Os usuários do Visual Studio devem reconhecer o paralelo.

Eu não sei o suficiente sobre o Windows para entender completamente as implicações de tudo isso, mas me sinto muito mal por reverter para uma situação em que pip install foo que instala um script foo não pode ser imediatamente executado como foo na linha de comando. Se estamos instalando em --user e isso não está em seu caminho por padrão, isso parece uma grande regressão para mim.

Não tenho certeza se entendi exatamente como o uso py.exe para os scripts não versionados funcionaria na prática e se realmente resolveria o problema. Não estou pessoalmente vinculado à criação de scripts exatamente como estamos hoje, então, se _funcionar_, acho que talvez possamos fazê-lo, mas eu teria que entender melhor as implicações antes de poder dar meu +1 nele.

Quanto à configuração do PATH no Windows, isso será quase impossível. Um instalador de todo o sistema só pode configurar variáveis ​​de ambiente de todo o sistema e não pode incluir expansões, portanto, você não pode definir caminhos diferentes para cada usuário.

Ah, eca. Eu tinha esquecido isso.

e talvez um atalho que execute o arquivo de lote
Na minha opinião, este é um atalho "Python 3.5 (32 bits) Command Prompt". Os usuários do Visual Studio devem reconhecer o paralelo.

... o que é horrível para aqueles de nós que usam o Powershell para tudo.

mas me sinto muito mal por reverter para uma situação em que pip install foo que instala um script foo não pode ser executado imediatamente como foo na linha de comando.

Acordado. Esta seria uma regressão ruim e precisa ser abordada. Eu só queria que alguém pudesse pensar em uma maneira :-)

Não tenho certeza se entendi exatamente como o uso de py.exe para os scripts não versionados funcionaria na prática

Eu acho que o ponto (que está apenas um pouco relacionado a py.exe ) é que o wrapper exe, em vez de invocar um interpretador Python específico e codificado como faz no momento, deve escolher dinamicamente o interpretador com base em "o que é o padrão" de alguma forma (registro, o arquivo py.exe ini, o que o Python %PATH% lhe der, ...). No entanto, não tenho certeza de como isso ajudaria, pois ainda precisaríamos de um diretório de scripts de usuário com versão (para evitar que os arquivos se sobrescrevam ou os arquivos sejam executados com interpretadores que não tenham o pacote instalado) e ainda precisaríamos não conseguir colocar isso no ponto certo em %PATH%.

... o que é horrível para aqueles de nós que usam o Powershell para tudo.

Acabei de tentar, e posso facilmente criar arquivos activate-py35.bat e activate-py35.ps1 que parecem e se comportam de forma idêntica (ou seja, todos escrevem activate-py35 e atualizam os caminhos). Ainda não é o ideal, mas possivelmente o melhor de uma situação ruim.

Não tenho certeza se entendi exatamente como o uso de py.exe para os scripts não versionados funcionaria na prática

Acho que o ponto (que está apenas um pouco relacionado a py.exe ) é que o wrapper exe, em vez de invocar um interpretador Python específico e codificado como faz no momento, deve escolher dinamicamente o interpretador com base em "o que é o padrão" de alguma forma

O "de alguma forma" é onde entra py.exe - as mesmas regras devem ser usadas. Se o iniciador fosse atualizado para verificar seu próprio nome, então, em vez de iniciar python.exe , ele poderia tentar iniciar 'scripts\\{}{}.{}.exe'.format(argv[0], major_version, minor_version) (com o ajuste de extensão adequado em argv[0] , etc.). Em seguida, os instaladores precisam usar um arquivo diferente para o iniciador não versionado do totalmente versionado (que seria inalterado a partir de hoje), mas esse arquivo seria apenas o py.exe normal com um novo nome. (Isso poderia ter sido ainda mais simples nos velhos tempos dos arquivos pip-script.py , mas agora que eles se foram...)

Mas como você diz, PATH ainda é o problema. Não tenho boas soluções, nem mesmo tantas soluções ruins. As variáveis ​​de ambiente são realmente destinadas aos administradores ou usuários para configurar, não aos instaladores.

Podemos ajustar como instalamos scripts para melhorar a experiência do usuário. É tudo um equilíbrio, o arquivo combinado .exe e .py tornou as coisas mais agradáveis ​​para os usuários, pois há apenas o arquivo .exe singular. No entanto, sinto que obter a melhor história por pip install foo && foo é mais importante do que essa coisa em particular, então, se precisarmos separar o .exe e o .py novamente, acho que é um boa troca por uma boa resposta.

A separação .exe / .py é o menor dos problemas :)

Na verdade, estou me aquecendo (ou aceitando de má vontade?) a ideia activate-py35 . Eu nunca fui fã do instalador adicionando Python ao PATH, e o comando py -m pip realmente não ganhou força (e nem funcionaria para, digamos, Sphinx). Escreverei uma descrição mais detalhada de como activate-py poderia funcionar e postarei no python-dev para ver se obtém alguma tração.

Esses arquivos activate-whatever seriam semelhantes aos de dentro do ambiente virtual? Exceto em vez de um ambiente virtual ser adicionado a $PATH , está adicionando os Pythons reais?

Sim, praticamente idêntico. No python-dev, acabei de sugerir que eles pegassem um parâmetro -x.y , passassem para py.exe e usassem sysconfig para obter os caminhos.

OK. Eu não tenho uma opinião sobre o quão ruim isso seria para os usuários do Windows, já que não sou um. Não soa absolutamente horrível (talvez?) mas isso é o mais longe que meu conhecimento do Windows pode me levar.

Em 10 de fevereiro de 2015, às 08:02, Donald Stufft escreveu:

Ah, e a coisa do script clobbering é um problema mais geral que não é
realmente relacionado a --user exatamente. O mesmo problema existe em todos os lugares
exceto instalações do Windows --global . Acho que a solução para esse problema é
uma preocupação/problema secundário que devemos resolver separadamente a esta questão.

Acordado.

Vamos usar o sinalizador --global .

+1

Provavelmente queremos algum tipo de aviso se estivermos instalando em --user e
~/.local/bin não está no $PATH .

+1, talvez com uma opção de configuração para suprimir o aviso?

Queremos algum tipo de opção default-install que essencialmente
desabilite o comportamento de fallback e apenas codifique para --global ou
--user .

+1

A partir do pip 6.0, temos arquivos de configuração específicos da máquina localizados em /etc/
no entanto, eles não são específicos para a versão do Python que está sendo executada
pip. Eu acho que é um bom recurso, embora um pouco separado também (e
pode ir de mãos dadas com a solução do problema de script clobbering também).

Sugiro uma ordem de pesquisa como:

  • pipX.Y.conf
  • pipX.conf
  • pip.conf

enraizado primeiro (?) em /etc/xdg/pip então /etc, onde XY é claro
número da versão major.minor. O primeiro encontrado, vence.

Vejo ainda uma grande questão em aberto: a longo prazo, o que queremos que aconteça quando
alguém faz sudo pip install foo ou melhor, se alguém tem permissão para
escrever no diretório site-packages ?

Observe que não existe apenas um diretório "site-packages". Por exemplo,
no Debian/Ubuntu não queremos sudo pip install para _ever_ instalar em
/usr/lib, mas apenas /usr/local/lib. E não se esqueça, é dist-packages aqui
não pacotes de sites (exceto em ~/.local porque $reasons).

Este é realmente um ponto importante que às vezes é esquecido (até por mim).
Donald o descreve melhor quando diz que há um diretório local do site e um
diretório local do fornecedor. No Debian, site-local é
/usr/lib/pythonX.Y/dist-packages e nenhum comando pip deve tocar nisso,
enquanto vendor-local é /usr/local/lib/pythonX.Y/dist-packages e é um
caso de uso documentado e popular para alguns administradores de sistema instalar pip
nesse diretório.

Então, o que eu sugiro, já que já estamos no caminho do arquivo de configuração, é
torná-los configuráveis, por exemplo

  • global_install_directory
  • global_install_as_sudo (verdadeiro/falso)
  1. Instale em --global . Esta é a opção mais compatível com versões anteriores
    e provavelmente representa o que os usuários esperam quando digitam isso. No entanto tem
    a desvantagem de que ele vai (silenciosamente) mexer com o Python global, que em muitos
    sistemas podem causar sistemas quebrados.

Com a configurabilidade acima, isso seria totalmente compatível com o Debian.
Os superusuários do Debian esperam que sudo pip install entre em
/usr/local/lib/pythonX.Y/dist-packages. Eu não diria que "mexe com o
system" porque não quebra o gerenciador de pacotes e, embora possa
substituir pacotes instalados pelo sistema (que vivem em
/usr/lib/pythonX.Y/dist-packages), ele faz isso de maneira definida e documentada.

  1. Instale em --user , isso protegerá contra sistemas quebrados (eu acho?)
    mas acho que ninguém esperaria que o usuário root obtivesse um
    /root/.local/ instalar.

Concordo, isso seria inesperado.

  1. Apenas erro e exija que o usuário selecione --user ou
    --global manualmente.

Eu ficaria bem com isso, mas veja a opção de configuração acima.

  1. Escolha uma das duas primeiras opções, mas forneça uma opção que as distros possam
    entre em /etc/ que habilitará a terceira opção.

Ei, que ótima opção!

A quarta opção pode ser a melhor, mas acho que devemos tentar
selecione uma das outras opções primeiro se pudermos chegar a algum tipo de solução
que funciona da mesma forma em todas as plataformas/cenários e faz sentido em todos eles
como eu preferiria ter um comportamento consistente entre plataformas, se possível.

Eu estou bem em ter um comportamento diferente definido pela plataforma, digamos, pip teve um
--dry-run opção que pelo menos informaria ao usuário exatamente o que estava acontecendo
fazer e onde.

Eu sinto que a terceira opção é provavelmente ruim, já que "eu escrevi
permission" será o cenário em que qualquer pessoa no Windows esteja em pré
Python 3.5, ou qualquer pessoa que use Conda, ou qualquer pessoa que use pyenv. Falhando
parece ser a coisa errada a fazer em todos esses casos e é algo que o usuário
hostil para arrancar.

Eu ficaria feliz se a configuração padrão fosse permitir --global install se você
tem permissão. Eu nem acho que o Debian mudaria isso (talvez outros tenham
uma opinião diferente, mas pelo menos isso nos dá opções).

Então eu acho que entre 1 e 2 realmente se resume a quão ruim é uma prática
achamos que é para as pessoas (conceitualmente) fazer sudo pip install --global foo .

No Debian, é um caso de uso esperado, desde que vá para /usr/local/lib.
Ele não pode ir para /usr/lib.

(Tudo isso descreve BTW comportamento fora de um venv.)

  • Quando --user é passado, sempre instalamos nos pacotes do site do usuário.

+1

  • Quando --global é passado, sempre instalamos no site global
  • pacotes.

Pacotes _vendor_ globais == +1, pacotes de sites globais == -1.

  • Quando nenhum é passado, implementamos um método de fallback que:

    1. Detecta se estamos em um ambiente virtual e, em caso afirmativo, age como se

      --global foi aprovado.

+1, embora eu repita que esse diretório dentro de um venv é nomeado
/lib/pythonX.Y/site-packages

  1. Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se
    --global foi passado.

Hmm, eu não tenho certeza sobre este.

  1. Olha para default-install e, se existir, usa --user ou
    -global com base nele.

+1

  1. Detecta se o usuário efetivo não tem permissão de escrita para global
    pacotes do site, e se eles não agem como se --user fosse passado.

+1

  1. Finalmente, se todos os outros métodos de detecção falharem, aja como se --global
    passou.

Também não tenho certeza.

Isso significaria nenhum período de depreciação e que a expectativa é que no
ausência de --user ou --global tentaremos fazer o melhor palpite baseado
sobre os recursos do Python em que estamos executando, o usuário efetivo e
qualquer método de instalação padrão configurado.

Parece um objetivo razoável.

Para ser claro, quando falo sobre "pacotes de sites globais", quero dizer principalmente "o que quer que distutils nos diga para instalar coisas globalmente". Como o próprio Python não tem uma distinção "fornecedor local" vs "site local", este será o mesmo diretório em qualquer downstream que não corrija seu Python. No debian, no entanto, será realmente um diretório dist-packages e "global" na verdade significa "site local". Isso não é algo que o pip precisa fazer algo especial para suportar, porque isso é resolvido pelos patches do Debuntu para o Python.

Em outras palavras, o pip já é instalado em /usr/local/../dist-packages/ no Debuntu, pois o Debuntu corrigiu os distutils para suportar essa distinção. A única vez que o pip mexeria com /usr/../dist-packages/ sem que o usuário passasse um sinalizador de algum tipo é que o pip desinstalaria os arquivos de lá (porque o pip não vê esse diretório como especial, apenas o vê como uma coisa em sys.path ). O Debian corrigiu o pip para evitar essa desinstalação de lá, e acho que o suporte real para isso depende de obter suporte real para pacotes de sites "local do fornecedor" no upstream do Python.

Provavelmente queremos algum tipo de aviso se estivermos instalando em --user e ~/.local/bin não estiver no $PATH

Quão frágil será esse aviso? Ele converteria para caminho absoluto? Seria insensível a maiúsculas e minúsculas em sistemas de arquivos insensíveis a maiúsculas e minúsculas? Trataria e/como equivalente no Windows? E quanto aos links simbólicos?

Se você estiver instalando um pacote que não instala nenhum script, o aviso é irrelevante de qualquer maneira.

Pessoalmente, acho que um aviso provavelmente fará mais mal do que bem.

Provavelmente queremos algum tipo de aviso se estivermos instalando em --user e
~/.local/bin não está no $PATH .

+1, talvez com uma opção de configuração para suprimir o aviso?

Nós poderíamos fazer isso usar uma coisa de avisos do Python para que as pessoas pudessem apenas silenciar
usando os avisos internos do Python. Se sentirmos a necessidade de silenciá-lo em
todo.

A partir do pip 6.0, temos arquivos de configuração específicos da máquina localizados em /etc/
no entanto, eles não são específicos para a versão do Python que está sendo executada
pip. Eu acho que é um bom recurso, embora um pouco separado também (e
pode ir de mãos dadas com a solução do problema de script clobbering também).

Sugiro uma ordem de pesquisa como:

  • pipX.Y.conf
  • pipX.conf
  • pip.conf

enraizado primeiro (?) em /etc/xdg/pip então /etc, onde XY é claro
número da versão major.minor. O primeiro encontrado, vence.

Divida isso em # 2417, pois acredito que é apenas tangencialmente relacionado a isso
discussão.

Vejo ainda uma grande questão em aberto: a longo prazo, o que queremos que aconteça quando
alguém faz sudo pip install foo ou melhor, se alguém tem permissão para
escrever no diretório site-packages ?

Observe que não existe apenas um diretório "site-packages". Por exemplo,
no Debian/Ubuntu não queremos que sudo pip install _ever_ instale em
/usr/lib, mas apenas /usr/local/lib. E não se esqueça, é dist-packages aqui
não pacotes de sites (exceto em ~/.local porque $reasons).

Este é realmente um ponto importante que às vezes é esquecido (até por mim).
Donald o descreve melhor quando diz que há um diretório local do site e um
diretório local do fornecedor. No Debian, site-local é
/usr/lib/pythonX.Y/dist-packages e nenhum comando pip deve tocar nisso,
enquanto vendor-local é /usr/local/lib/pythonX.Y/dist-packages e é um
caso de uso documentado e popular para alguns administradores de sistema instalar pip
nesse diretório.

Então, o que eu sugiro, já que já estamos no caminho do arquivo de configuração, é
torná-los configuráveis, por exemplo

  • global_install_directory
  • global_install_as_sudo (verdadeiro/falso)

pip realmente não controla isso (quero dizer, obviamente no alto nível ele faz
porque é aquele que move os arquivos), eles vêm de distutils/sysconfig.

Eu acho que o pip provavelmente nunca deve tocar em um diretório local do fornecedor, a menos que
algum tipo de sinalizador foi dado como --vendor que permitiria que os fornecedores usassem
pip em sua cadeia de construção. Este conceito realmente não existe fora do debuntu
agora e seus patches já lidam com isso, então eu não acho que seja super
relevantes para esta discussão, exceto para notar que quando eu digo
"pacotes de sites globais" eu quis dizer /usr/local/.../dist-packages no Debubuntu
e os pacotes "site-local" em algum momento se o Python aceitar o Debuntu
sistema a montante.

  1. Instale em --global . Esta é a opção mais compatível com versões anteriores
    e provavelmente representa o que os usuários esperam quando digitam isso. No entanto tem
    a desvantagem de que ele vai (silenciosamente) mexer com o Python global, que em muitos
    sistemas podem causar sistemas quebrados.

Com a configurabilidade acima, isso seria totalmente compatível com o Debian.
Os superusuários do Debian esperam que sudo pip install entre em
/usr/local/lib/pythonX.Y/dist-packages. Eu não diria que "mexe com o
system" porque não quebra o gerenciador de pacotes e, embora possa
substituir pacotes instalados pelo sistema (que vivem em
/usr/lib/pythonX.Y/dist-packages), ele faz isso de maneira definida e documentada.

Sim, "mexe com o sistema" pode ser muito duro. Principalmente eu quero dizer isso
sudo pip install foo pode quebrar coisas se o sistema depender de foo e
você instala uma versão incompatível das coisas. No entanto, esse mesmo caso vale
true para basicamente qualquer coisa que você instalar em `/usr/local``.

  • Quando --global é passado, sempre instalamos no site global
  • pacotes.

Pacotes _vendor_ globais == +1, pacotes de sites globais == -1.

Você quer dizer isso ao contrário certo?

  • Quando nenhum é passado, implementamos um método de fallback que:

    1. Detecta se estamos em um ambiente virtual e, em caso afirmativo, age como se

      --global foi passado.

+1, embora eu repita que esse diretório dentro de um venv é nomeado
/lib/pythonX.Y/site-packages

Sim, novamente, apenas perguntamos ao Python onde está esse diretório, não o computamos
nós mesmos, então "onde esse diretório está" é uma coisa venv/virtualenv.

  1. Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se
    --global foi aprovado.

Hmm, eu não tenho certeza sobre este.

Eu não acho que haja alguma maneira de contornar isso, se os pacotes do site do usuário estiverem desabilitados, eu
não acho que devemos instalar lá porque não temos como saber
se essa desativação significa que não há nenhum pacote de site do usuário ou por quê. Nós só podemos
suponha que não exista.

  1. Finalmente, se todos os outros métodos de detecção falharem, aja como se --global
    passou.

Também não tenho certeza.

Isso basicamente se resume a:

Se não encontrarmos um motivo, devemos usar --user, como um sinalizador --user, ou
não ter permissões para gravar no diretório, então não o use. este
é o que vai manter sudo pip install foo sem uma bandeira --global
trabalhando. Isso também significa que esta é a regra mais importante para não quebrar
software funcional que espera que sudo pip install foo aja dessa maneira.

Provavelmente queremos algum tipo de aviso se estivermos instalando em --user e ~/.local/bin não estiver no $PATH

Quão frágil será esse aviso? Ele converteria para caminho absoluto? Seria insensível a maiúsculas e minúsculas em sistemas de arquivos insensíveis a maiúsculas e minúsculas? Trataria e/como equivalente no Windows? E quanto aos links simbólicos?

Se você estiver instalando um pacote que não instala nenhum script, o aviso é irrelevante de qualquer maneira.

Pessoalmente, acho que um aviso provavelmente fará mais mal do que bem.

Bem, poderíamos implementá-lo como o (equivalente de plataforma cruzada de):

def user_bin_on_path():
    paths = os.environ.get("PATH").split(":")
    for path in paths:
        if os.path.realpath(path) == os.path.realpath(USER_BIN_DIR):
            return True
    return False

Algo assim deve lidar com links simbólicos, separadores de caminho e coisas do tipo, eu acho. Diabos nos detalhes e talvez não possamos obter precisão o suficiente para cobrir os vários casos de canto de plataforma cruzada.

Eu concordo que o aviso é irrelevante se não houver scripts sendo instalados, e eu quis dizer que só nos incomodaríamos com o aviso quando estivermos instalando scripts.

A ideia básica é que eu não quero que alguém faça algo como pip install [--user] foo onde o --user está implícito, e então faça foo e obtenha um "comando não encontrado" sem nenhuma orientação sobre por que pode não ser encontrado. Um aviso, pelo menos, dirá que eles precisam adicionar coisas ao PATH. Também pode ajudar os usuários no Windows a adicionar seu diretório de usuário ao PATH manualmente (ou executar algum script para fazer isso), o que pode aliviar a necessidade dos scripts activate que Steve apontou. Embora eu ache que isso ainda significaria que os valores do sistema têm precedência sobre os valores do usuário, de modo que ainda pode ser confuso, pois a ordem de PATH e sys.path ainda seria invertida.

Doh. Esqueci que realpath canonizou o caminho. Sim, claro que funciona bem o suficiente.

O que me incomoda é que _se_ o teste erroneamente vê um problema, o usuário recebe um aviso irritante e incorreto sem nenhuma maneira de evitá-lo além de alterar seu sistema para solucionar um erro por parte do pip. Mas dado que o teste que você está propondo é provavelmente robusto o suficiente, e só fazemos a verificação se estivermos instalando scripts, o problema provavelmente é raro o suficiente para ser ignorado.

Tudo bem, acho que temos um amplo acordo aqui. Acho que o próximo passo é fazer um patch. Eu vou em frente e tentar conseguir algo mais tarde esta noite ou amanhã.

Em 10 de fevereiro de 2015, às 12h14, Donald Stufft escreveu:

A ideia básica é que eu não quero que alguém faça algo como pip install [--user] foo onde o --user está implícito, e então faça foo e
obter um "comando não encontrado" sem nenhuma orientação sobre por que não pode ser
encontrado.

Debian, e talvez outros Linux, na verdade tem um pacote de comando não encontrado
que solicita ao usuário que instale um pacote se invocar um comando que
não está instalado.

% paisagem de tinta
O programa 'inkscape' não está instalado no momento. Você pode instalá-lo digitando:
sudo apt-get install inkscape

Talvez pudéssemos usar isso para plataformas de suporte.

Em 10 de fevereiro de 2015, às 12h06, Donald Stufft escreveu:

  • Quando --global é passado, sempre instalamos no site global
  • pacotes.

Pacotes _vendor_ globais == +1, pacotes de sites globais == -1.

Você quer dizer isso ao contrário certo?

Eu poderia ter minha terminologia misturada, então serei explícito:

/usr/local/lib/pythonX.Y/dist-packages == +1
/usr/lib/pythonX.Y/dist-packages == -1

mas como você disse anteriormente, isso não é algo que pip realmente precisa se preocupar
sobre uma vez que é herdado de distutils e distutils do Debuntu é corrigido
para fazer a coisa certa.

  1. Detecta se os pacotes do site do usuário estão desabilitados e, em caso afirmativo, age como se
    --global foi aprovado.

Hmm, eu não tenho certeza sobre este.

Eu não acho que haja alguma maneira de contornar isso, se os pacotes do site do usuário estiverem desabilitados, eu
não acho que devemos instalar lá porque não temos como saber
se essa desativação significa que não há nenhum pacote de site do usuário ou por quê. Nós só podemos
suponha que não exista.

Oh, eu vejo o que você quer dizer agora. Acho que isso faz sentido. Minha preocupação é que
pode ser mais difícil prever o que o pip realmente vai fazer, mas como eu
digamos, eu ficaria feliz com um sinalizador --dry-run para que o pip possa _tell_ inequivocamente
você o que vai fazer.

  1. Finalmente, se todos os outros métodos de detecção falharem, aja como se --global
    passou.

Também não tenho certeza.

Isso basicamente se resume a:

Se não encontrarmos um motivo, devemos usar --user, como um sinalizador --user, ou
não ter permissões para gravar no diretório, então não o use. este
é o que vai manter sudo pip install foo sem uma bandeira --global
trabalhando. Isso também significa que esta é a regra mais importante para não quebrar
software funcional que espera que sudo pip install foo aja dessa maneira.

Entendo. Eu acho que está tudo bem, já que o principal caso anti-uso que queremos evitar é:

normal_user$ pip instalar foo
Ei, você não tem permissão
normal_user$ sudo pip install foo
EI, VOCÊ ACABOU DE BORCAR SEU SISTEMA

e a regra "não ter permissões para gravar no diretório implica --user"
cuida disso.

Ah sim, eu esqueci o comando não encontrado. Pode ser útil. A propósito, você sabe o lugar certo para propor que o devubtu tenha o bin local do usuário no caminho por padrão?

Em 10 de fevereiro de 2015, às 16h05, Barry Warsaw [email protected] escreveu:

Em 10 de fevereiro de 2015, às 12h14, Donald Stufft escreveu:

A ideia básica é que eu não quero que alguém faça algo como pip install [--user] foo onde o --user está implícito, e então faça foo e
obter um "comando não encontrado" sem nenhuma orientação sobre por que não pode ser
encontrado.

Debian, e talvez outros Linux, na verdade tem um pacote de comando não encontrado
que solicita ao usuário que instale um pacote se invocar um comando que
não está instalado.

% paisagem de tinta
O programa 'inkscape' não está instalado no momento. Você pode instalá-lo digitando:
sudo apt-get install inkscape

Talvez pudéssemos usar isso para plataformas de suporte.


Responda a este e-mail diretamente ou visualize-o no GitHub.

Em 10 de fevereiro de 2015, às 13h17, Donald Stufft escreveu:

Ah sim, eu esqueci o comando não encontrado. Pode ser útil. Aliás, você
saber o lugar certo para propor que o devubtu tenha o usuário local bin no
caminho por padrão?

Não definitivamente, mas talvez os pacotes adduser ou passwd? O primeiro possui
/usr/sbin/adduser e o último possui /usr/bin/useradd.

Não tenho certeza se isso ajuda, mas…

  • ~/.local/bin não está no $PATH de muitas pessoas, há algo que possa ser feito sobre isso?

Alguns outros projetos usam /etc/profiled.d/ para adicionar diretórios ao $PATH. Pelo menos no Antergos eu vejo o seguinte (a menos que eu entenda mal o que eles fazem) jre.csh, jre.sh, perlbin.csh, perlbin.sh.

# Do not change this unless you want to completely by-pass Arch Linux' way
# of handling Java versions and vendors. Instead, please use script `archlinux-java`
setenv PATH "${PATH}:/usr/lib/jvm/default/bin"
# Do not change this unless you want to completely by-pass Arch Linux' way
# of handling Java versions and vendors. Instead, please use script `archlinux-java`
export PATH=${PATH}:/usr/lib/jvm/default/bin
# Set path to perl scriptdirs if they exist
# https://wiki.archlinux.org/index.php/Perl_Policy#Binaries_and_Scripts
# Added /usr/bin/*_perl dirs for scripts
# Remove /usr/lib/perl5/*_perl/bin in next release

[ -d /usr/bin/site_perl ] && setenv PATH ${PATH}:/usr/bin/site_perl
[ -d /usr/lib/perl5/site_perl/bin ] && setenv PATH ${PATH}:/usr/lib/perl5/site_perl/bin

[ -d /usr/bin/vendor_perl ] && setenv PATH ${PATH}:/usr/bin/vendor_perl
[ -d /usr/lib/perl5/vendor_perl/bin ] && setenv PATH ${PATH}:/usr/lib/perl5/vendor_perl/bin

[ -d /usr/bin/core_perl ] && setenv PATH ${PATH}:/usr/bin/core_perl

# If you have modules in non-standard directories you can add them here.
#export PERLLIB=dir1:dir2
# Set path to perl scriptdirs if they exist
# https://wiki.archlinux.org/index.php/Perl_Policy#Binaries_and_Scripts
# Added /usr/bin/*_perl dirs for scripts
# Remove /usr/lib/perl5/*_perl/bin in next release

[ -d /usr/bin/site_perl ] && PATH=$PATH:/usr/bin/site_perl
[ -d /usr/lib/perl5/site_perl/bin ] && PATH=$PATH:/usr/lib/perl5/site_perl/bin

[ -d /usr/bin/vendor_perl ] && PATH=$PATH:/usr/bin/vendor_perl
[ -d /usr/lib/perl5/vendor_perl/bin ] && PATH=$PATH:/usr/lib/perl5/vendor_perl/bin

[ -d /usr/bin/core_perl ] && PATH=$PATH:/usr/bin/core_perl

export PATH

# If you have modules in non-standard directories you can add them here.
#export PERLLIB=dir1:dir2

Como um usuário pip aleatório, só quero dizer _obrigado_ por trabalhar em problemas de experiência do usuário como este e como os outros capturados no marco Melhorar nossa experiência do usuário . Existe algum lugar onde eu possa contribuir financeiramente para este esforço?

Como um aparte, eu uso o Homebrew e sempre apreciei o fato de que eu poderia apenas brew install something e funcionaria sem nenhum problema com as permissões.

Depois que entendi por que a instalação com o Homebrew nunca exigia sudo , tentei adquirir o hábito de fazer pip install --user something , mas ironicamente o Homebrew desabilita isso devido a um bug relatado no distutils.

Dada a popularidade do Homebrew no OS X, talvez vocês queiram examinar essa suposta incompatibilidade do Homebrew e pip install --user .

De qualquer forma, +1 de mim ao tornar --user o padrão.

Um rápido acompanhamento. Didier carregou uma mudança no pip do Ubuntu em vívido que definiu --user como padrão. Eu também permiti, mas agora acho que foi um erro e pretendo reverter isso para wily (mas provavelmente não será SRU uma mudança para vivid). Consulte https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1460203 para obter detalhes e lógica.

+1 por permitir que o upstream conduza o tempo dessa mudança, pois a distinção entre usuário e sistema já é confusa o suficiente sem que as diferenças de plataforma entrem em jogo.

Dito isso, pode ser razoável que as distribuições Linux comecem a mudar o padrão para --user assim que --global support chegar ao pip upstream (pip 8?), já que fazer instalações globais no Linux, em vez de por usuário ou per-venv, está bem estabelecido como sendo uma má ideia com efeitos colaterais potencialmente imprevisíveis.

Eu contei para @warsaw em particular, mas vou dizer aqui também:

Acho que essa mudança é importante e pretendo voltar ao meu pull request para terminá-lo. No entanto, sou uma pessoa sobrecarregada por vários projetos e, no momento, o Warehouse é mais importante para mim do que essa mudança porque o legado PyPI está se tornando cada vez mais pesado para operar e sinto que precisamos substituí-lo o mais rápido possível. Portanto, meu tempo no pip não está focando em fazer muitas mudanças sozinho, mas sim em orientar as mudanças que outros contribuidores fazem, bem como qualquer coisa do processo de lançamento.

Dito isto, se alguém realmente se importa com o lançamento desse recurso mais cedo ou mais tarde, eles podem pegar meu trabalho e terminá-lo e ficarei feliz em revisá-lo (e com sorte mesclá-lo). Fico feliz em conversar sobre isso com qualquer pessoa que queira fazer isso e fornecer orientação sobre a mudança. Caso contrário, vai esperar até que eu termine os itens que são mais urgentes para mim.

Talvez valha a pena repetir neste momento:

Se acabarmos decidindo contra 'padrão para --user', devemos considerar as alternativas menos disruptivas

  1. Fallback para --user (se a instalação falhar devido a erros de permissões)
  2. (Se a instalação falhar devido a erros de permissão), incentive o usuário (em letras grandes e amigáveis) a tentar --user

FWIW, agora que o instalador do Windows para Python 3.5 incentiva fortemente uma instalação por usuário, não estou tão preocupado com essa mudança ocorrendo no pip. Provavelmente seria uma opção de configuração melhor para distros (com a substituição --global ) do que um novo padrão ou um fallback.

Só queria marcar com +1 este problema e agradecer por trabalhar nisso! Atualmente, estamos administrando uma escola de verão científica de Python e tivemos muitas pessoas sudo pip install quando se depararam com problemas de permissão.

FWIW Eu sou a favor de padronizar para --user , ou voltar para --user se a instalação falhar devido a erros de permissão. Nesse caso, eu preferiria dar a eles as instruções para reverter o que eles fizeram (por exemplo, We installed to your user directory. If you don't want this, then 'pip uninstall my_package' ) em vez de falhar e dizer a eles como tentar novamente.

Eu vejo muitos relatórios de bugs no mock devido a --user - pelo menos no Ubuntu onde --user's place no caminho é após dist-packages, e então o pip instalado não é realmente usado, para qualquer dependência comum (como seis) que está em pacotes dist.

Eles colocaram _depois_ dist-packages ? Isso é uma instalação quebrada IMO.

Certo, as instalações do usuário devem estar antes dos pacotes site(/dist) e, em seguida, os scripts e utilitários do sistema devem ser executados com -I (ou -Es no Python 2).

Sim eu concordo :). Pode ser corrigido em vívido, mas eu definitivamente pareço relatórios onde as coisas estão vindo do lugar totalmente errado.

Acabei de usar o sistema pip para instalar setuptools na minha máquina vívida, para experimentar.

>>> import setuptools
>>> setuptools.__path__
['/home/robertc/.local/lib/python2.7/site-packages/setuptools']
>>> import sys
>>> sys.path
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/robertc/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/home/robertc/work/mock']

Então este é sensato. Mas confusamente isso foi introduzido em vívido - então IDK. Vou ver se consigo desenterrar um reprodutor em algum momento (para arquivar no Ubuntu BTS)

Paginação @warsaw

Os pacotes de sites do usuário podem acabar sendo reorganizados após os pacotes de sites globais pelos arquivos .pth malignos do setuptools. Esses eram um problema recorrente para mim até que aprendi a nunca usar setup.py diretamente - eu instalava algo e, de repente, estava usando versões mais antigas de todos os tipos de outras coisas. Depois de algumas vezes, escrevi uma ferramenta agressiva para desmanchar meu sistema.

Eu acho que, pelo menos, por enquanto, o pip deve apenas imprimir uma mensagem amigável pedindo ao usuário para executar --user se o comando falhar. Embora alterá-lo para o padrão tenha seus benefícios, imprimir uma mensagem melhor não deve ser muito difícil.

É uma boa "solução rápida" para o problema até que realmente mudemos para o padrão --user .

Um --global, --system ou --no-user também é necessário caso o modo de usuário esteja definido em /etc/pip.conf. Não há uma maneira fácil para os usuários substituirem isso até onde eu sei.

É uma boa "solução rápida" para o problema

Atualização tardia: #4233 fez isso.

As pessoas (especialmente os recém-chegados) que não estão usando o Windows devem realmente ser direcionadas para https://github.com/pyenv/pyenv se quiserem ter uma boa experiência. PEP 370 não faz muito sentido para mim hoje, especialmente porque ~/.local é XDG_DATA_HOME.

Acho que não serei o único que optará por não aceitar esse comportamento se/quando ele vier. Espero que a transição seja suave e eu não precise alterar a forma como meu sistema funciona e passar sinalizadores CLI adicionais, porque estou muito feliz com pyenv. Claro, não sei o quão bem o pyenv funciona com o Windows, mas o subsistema bash pode ajudar lá ...

@jcrben pyenv faz algumas suposições sobre como as pessoas estão usando Python (e, em particular, como estão adquirindo seus binários Python), o que significa que funciona muito bem para pessoas para quem essas suposições são válidas, mas não é suficientemente universal para ser a recomendação padrão (é semelhante a conda a esse respeito).

O padrão --user no nível pip não terá efeito dentro de ambientes virtuais Python configurados corretamente, portanto, o impacto dessa alteração em gerenciadores de ambiente de terceiros como conda e pyenv será que eles precisarão garantir que estão sinalizando corretamente o status do ambiente de uma forma que pip e outras ferramentas irão detectar (ou seja, a forma virtualenv informa, ou a forma como o venv da biblioteca padrão faz).

Proposta relacionada: https://github.com/pypa/pip/issues/1056#issuecomment -218130183.

~ Foi considerado permitir que o usuário personalize o diretório (provavelmente através de uma variável env) para evitar instalar diretamente em ~/.local ? Eu provavelmente prefiro aninhá-los em ~/.local/pip ou algo assim - no que me diz respeito, o Python não tem direito especial ao nível superior desse espaço compartilhado. ~ No 9.0.1, parece aninhar coisas em ~/.local/lib/python<version> além de adicionar executáveis ​​a ~/.local/bin que eu acho que está bem ...

@jcrben Sim, o local de destino é na verdade o diretório do site do usuário do Python, que espelha o esquema de nomenclatura para o diretório de pacotes do site do sistema: https://docs.python.org/3/library/site.html#site.USER_SITE

Isso já é configurável no nível do interpretador por meio da variável de ambiente PYTHONUSERBASE : https://docs.python.org/3/using/cmdline.html#envvar -PYTHONUSERBASE

Para os interessados, acabei de lançar https://github.com/ofek/hatch que tem os comandos de pacote install , uninstall e update que tem como padrão esse comportamento. Para alterar o sistema, os usuários podem usar a opção -g/--global semelhante a https://github.com/npm/npm.

Dado o recente problema com pacotes infectados por malware no PyPI , acho que é do interesse do pip fazer o que puder para desencorajar o uso de sudo pip install ... , especialmente levando em consideração que os scripts de configuração podem executar código arbitrário na instalação. Instalar pacotes infectados como usuário já é ruim o suficiente, mas é muito pior se eles forem instalados como root.

O padrão para instalações do usuário significa que menos pessoas adicionarão sudo ao comando pip, o que significa que o malware instalado acidentalmente pode fazer menos.

Como um próximo passo concreto, lancei um problema separado para a adição de um sinalizador --global : https://github.com/pypa/pip/issues/4865

Isso é quase certamente uma má ideia em ambientes virtualenv ou conda. O que quer que seja instalado em .local quando um ambiente está ativo pode facilmente quebrar outro ambiente. Então, qual é o pensamento nesses casos?

cc @msarahan @kalefranz

Este problema não se aplica quando dentro de um ambiente virtual ativo - aplica-se apenas quando nenhum ambiente ativo é detectado e nenhuma das opções de definição de destino ( --prefix , --root , etc) foi fornecida na linha de comando.

Como isso está sendo determinado?

Estamos considerando desabilitar por padrão ~/.local em sys.path para python dentro de ambientes conda, que por definição é qualquer python instalado pelo conda. É complicado embora. De qualquer forma, podemos acabar violando as expectativas de um grupo de usuários. Discussão em https://github.com/conda/conda/issues/7173

O pip não conseguiu carregar nenhum argumento de variáveis ​​de ambiente começando com PIP_ ? Isso funciona para --user ? Qual seria o nome completo da variável?

Isso seria PIP_USER .

Documentos: https://pip.pypa.io/en/stable/user_guide/#environment -variables

PIP_USER=yes para ser exato, obrigado! Usar variáveis ​​de ambiente é muito mais fácil para uso de CI, pois você só precisa defini-las uma vez e elas serão usadas sempre que os comandos forem chamados.

Eu tive que fazer uma lógica muito feia para o travis onde aparentemente alguns estágios são executados como usuário normal sem virtualemv e alguns dentro de um virtualenv, e você não tem ideia de qual seria.

dentro do virtualenv é provável que —user falhará se você não usar pacotes de sites (o que está causando outros problemas).

Este mento que eu tive para detectar virtualenv no bash e evitar adicionar o —user ou a execução falhará.

Isso é feio e me fez perder muito tempo depurando, tenho certeza que outros enfrentarão o mesmo.

Acho que precisamos de uma opção que ative um fallback em relação à instalação: como instalá-lo no usuário, se puder, e fallback para o sistema.

pip deve falhar apenas se não encontrar um local para instalar um pacote.

Algum movimento sobre isso?

Eu não vi isso mencionado, mas talvez o pip deva reclamar se --user for passado quando executado sob sudo.

Esses problemas não resolvidos afastam os programadores do pip e até do python e os forçam a usar outros pacotes ou mesmo outras linguagens de programação como javascript e npm com menos problemas como esse. Para um novo iniciante que deseja usar python, essas opções extras necessárias são frustrantes.

Por que --user seria o padrão? Não pode ser especificado explicitamente? Não consigo executar pip --target porque ele reclama que não pode ser usado em conjunto com o usuário. Alguma ideia de como evitá-lo?

@dmikov : não é o padrão. A menos que você esteja usando a versão quebrada do Debian/Ubuntu , nesse caso você pode contornar --user sendo definido automaticamente usando: PIP_USER=0 pip install -t ... . Ou melhor ainda, instale uma versão oficial e use-a.

Eu sonhei à noite com a opção --user se tornando o padrão (sem brincadeira), alguma chance de meus sonhos se tornarem realidade em breve?

Preciso de ajuda para instalar o pygame, ele continua dizendo sintaxe inválida

eu usei
python3 -m pip install -U pygame --user
isso é errado o que eu faço?

@flamedro56 : em vez de comentar um problema aleatório, abra um novo e forneça mais informações: versão do Python, versão do pip, sistema operacional, saída do comando ...

Instalador reCAPTCHA

Que tal ter uma nova opção de configuração default=system,user? Seria explícito o suficiente para que ninguém pensasse que significa "sempre usuário, mesmo em virtualenv". Isso permitiria um caminho de migração gracioso.

Veja #4575.

Parece que o Manjaro está tentando definir --user como padrão.

Há alguma novidade do upstream sobre esse problema?

@Tids : "filesystem-2018.9-3 adiciona $HOME/.local/bin ao seu $PATH por padrão." é a peça chave extra que Manjaro está fazendo certo.

O Debian combina "padrão para --user" no nível do Python com "$HOME/.local/bin não está no seu $PATH por padrão" no nível da conta do usuário, e esse é o combo que quebra as coisas.

Em #7002, tentei fazer com que o pip faça uma instalação de usuário por padrão quando o diretório global de pacotes de sites não é gravável e os pacotes de sites do usuário estão habilitados. Isso deve evitar em grande parte fazer uma instalação do usuário quando você pretendia instalar em um env, desde que você tenha permissão para modificar o env.

Estou procurando discutir a ideia primeiro - não vamos nos perder em revisar a implementação antes de pensarmos se faz sentido fazer isso.

Vale a pena notar que misturar instalações de usuários e instalações de não usuários (do próprio pip) está repleta de problemas - veja #7209 como um exemplo recentemente.

Embora não esteja diretamente relacionado a esse problema (e, de fato, se usarmos como padrão o usuário, isso pode aliviar um pouco a situação), ele enfatiza a necessidade de pensar cuidadosamente sobre como lidamos com qualquer transição para --user como padrão.

(Estou principalmente adicionando este comentário aqui para que seja gravado em algum lugar - não é principalmente um problema de pip, mas sim uma complicação de como o diretório USER_SITE do Python funciona em geral, que não é suficientemente bem compreendido pelos usuários que instalam com --user ).

Parece que o problema é que PATH (para localizar comandos) e sys.path (para localizar importações do Python) têm prioridades opostas, então o script do iniciador de uma instalação tenta carregar o pacote do de outros. Presumivelmente, não é específico para pip - pode afetar qualquer pacote que instale um script.

Não tenho certeza do que podemos fazer sobre isso, se é que podemos fazer alguma coisa, mas concordo que vale a pena pensar nisso.

Sim, essa é a principal "complicação do USER_SITE" que eu tinha em mente. IMO, preterir scripts wrapper e suportar apenas python -m pip é a solução mais eficaz. (Não sou contra os wrappers em si, mas os problemas que vemos com eles geralmente são pessoas executando acidentalmente o wrapper errado , portanto, corrigir problemas de script de wrapper geralmente não é um problema de pip como tal, mais um "diagnóstico e correção de configuração incorreta do ambiente do usuário " questão)

Você quer dizer depreciar o script wrapper pip ou depreciar scripts wrapper como algo que o pip pode instalar?

Estou certamente -1 no último - a capacidade de instalar comandos é muito útil, mesmo que cause problemas.

Descontinuar pip em favor de python -m pip pode ser mais razoável. À medida que o pip é instalado no ambiente Python em que está sendo executado, faz sentido deixar claro qual é. Mas ainda seria uma perda de conveniência e uma grande ruptura no que as pessoas estão acostumadas.

Eu quis dizer especificamente os scripts de wrapper para o próprio pip. Concordo que é uma perda de conveniência, e eu não seria contra mantê-los de alguma forma (#3164 sugere ter um novo projeto pip-cli que apenas forneça os invólucros), mas o ponto principal seria python -m pip para ser o meio suportado para executar o pip.

Não foi possível chamar o script de wrapper pip mostrar um aviso se o python atual (no PATH ou o que seria usado com python -m pip ) não for o python usado por pip ? Talvez até delegue para python -m pip se for chamado dessa forma?

Da mesma forma, o pipenv avisa se o usuário já estiver em um virtualenv e, se estiver, usa esse virtualenv em vez de gerenciar seu próprio, após emitir um aviso.

Ok, observando aqui que o #7002 foi aprovado por 3 dos 6 mantenedores de pip neste momento.

Isso faz com que o pip mude de instalações de não usuário para instalações de usuário por padrão, na maioria dos casos em que realmente deveríamos fazer instalações de usuário de qualquer maneira. Tenho duas preocupações mais amplas em fazer essa mudança, que devemos descobrir antes de fazer o lançamento que faz esse aprimoramento.

  • Queremos um mecanismo que exclua explicitamente as instalações do usuário quando mudarmos para ele por padrão? Se sim, como seria diferente de --no-user ? (Estou a favor de renomear --no-user para --global como uma opção de exclusão explícita).
  • Qual é a nossa estratégia de "transição"?

    • Como queremos comunicar esta mudança?

    • dizer aos usuários para serem cuidadosos ao fazer esta atualização?

    • Que tipos de problemas esperamos que os usuários levantem quando essa mudança for implementada + lançada?

Eu diria que --global é um nome errado se você estiver dentro de um ambiente. Para flit install , o oposto de --user é --env , que eu pretendia incluir o "ambiente Python do sistema", mas também não acho que esteja totalmente claro. Talvez --no-user ainda seja a melhor escolha - é claramente o oposto de --user .

Eu acho que --no-user (ou a variável de ambiente equivalente ou entrada de configuração) deve retornar o comportamento existente, já que o padrão no momento é efetivamente user = False .

O único cenário que encontrei em que a alteração seria confusa é se você acha que tem permissão para instalar em um ambiente (com o site do usuário ativado, por exemplo, conda) quando na verdade não tem: uma falha é mais clara do que fazer um instalação do usuário, mesmo que haja uma mensagem de log sobre isso. Eu não pensei em nenhuma boa maneira de melhorar isso.

Também é possível que a detecção de capacidade de escrita possa dar errado. Um falso positivo apenas fornece o comportamento existente (tente e falhe em fazer uma instalação normal). Um falso negativo faria uma instalação do usuário quando poderia ter feito uma instalação normal.

Ele faz com que o pip mude de instalações de não usuário para instalações de usuário por padrão.

Não (por exemplo) no Windows, onde (por padrão) a instalação do Python é uma instalação por usuário e os pacotes do site são graváveis ​​por padrão. Isso é algo que eu prefiro em geral sobre o #7002, porque minha experiência desde que este problema (#1668) foi aberto é que é muito fácil entrar em confusão com ambientes "mistos" onde você tem pacotes como pip instalados tanto em pacotes de sites e site do usuário. Então, agora sou a favor de fazer instalações do sistema, se possível, e apenas fazer instalações do usuário em casos como Pythons gerenciados pelo sistema Linux, onde os pacotes do site não podem ser gravados.

Tendo dito isto:

  1. Parece não haver sentido para uma opção --no-user , pois #7002 significa que você obtém uma instalação do usuário somente se uma instalação do sistema falhar de qualquer maneira.
  2. A maior coisa que acho que precisamos comunicar em relação à transição é que as pessoas precisam ter muito cuidado com várias instalações, e isso é algo que só pode ser tratado pela compreensão e educação do usuário, não por qualquer solução alternativa no pip. É basicamente um problema central do Python. Poderíamos estender pip check para relatar quando há um site e um usuário instalando um pacote e o usuário está sombreando o site, eu acho...

Parece não haver sentido em uma opção --no-user

Para ser claro, isso já existe, embora provavelmente não seja útil com frequência. Se você tiver user=true em um arquivo de configuração, --no-user deve substituir isso.

Para ser claro, isso já existe

Desculpe, eu deveria ter sido mais claro. Não vejo sentido em ter "um mecanismo para excluir explicitamente as instalações do usuário assim que mudarmos para ele por padrão", pelo menos no sentido que presumo que @pradyunsg quis dizer, que é sobre a exclusão do comportamento #7002, que não é o mesmo que "mudar para instalações de usuário por padrão", como eu disse.

Na verdade, não tenho certeza de que seja mais claro ;-) Talvez tudo o que eu queira dizer seja "não precisamos de mais opções do que as que temos atualmente" ...

Hmm... @pfmoore Após #7002, o que é necessário para chamar esse problema de resolvido?

PS: Eu escrevi esse comentário anterior com pressa e foi postado acidentalmente. As balas estão OK; Eu ainda estava redigindo o parágrafo antes dele, quando foi postado. Desculpe qualquer confusão que possa ter causado.

@pradyunsg Dado que agora estou muito menos inclinado a sentir que --user como padrão é uma boa ideia, a menos que seja absolutamente necessário (os casos #7002 abordam), prefiro dizer que podemos abandonar esse problema como não é mais uma boa ideia agora que o #7002 está pronto.

Tomando seus 2 pontos de bala como coisas que podemos precisar para contar #7002 como completo, meus comentários acima cobrem isso.

Eu segui as notas de lançamento aqui.
https://pip.pypa.io/en/stable/news/#id3
"Padrão para fazer uma instalação do usuário (como se --user foi passado) quando o diretório principal de pacotes de sites não é gravável e os pacotes de sites do usuário estão habilitados. (#1668)"

Minhas compilações agora estão falhando com

ERROR: Can not perform a '--user' install. User site-packages are not visible in this virtualenv.

Isso parece corrigido removendo o --user dos meus comandos pip.

Esse era o comportamento esperado? As notas de lançamento parecem não refletir isso.

link para o script que agora falha no pip 20.0.1 (remover o --user corrige a falha difícil)
https://github.com/lfit/releng-global-jjb/blob/master/shell/python-tools-install.sh

Se estiver correto que os pacotes do site do usuário não sejam importáveis ​​desse ambiente, esse é o comportamento esperado, mas é ortogonal a este PR. Essa verificação foi introduzida anos atrás (#567), mas parece que foi quebrada com venv até recentemente (#7155). Há uma nota de lançamento para isso:

Manuseie corretamente os pacotes de site do sistema, em ambientes virtuais criados com venv (PEP 405).

Ah sim, obrigado por seus comentários. Eu percebi isso...
meu script estava preenchendo .local/bin/
quando eu corri

python3 -m venv ~/.local

e então em um shell de login do ubuntu (#!/bin/bash -l) .local/bin é adicionado ao caminho (então chamar python3 agora chama o executável .local/bin/python3) O que não queremos.
Eu nunca precisei executar python3 -m venv ~/.local
ou chamar meus scripts de um shell de login e remover ambos ou um desses problemas o corrige.

#fresh ubuntu docker
root<strong i="13">@7d8107816f64</strong>:/# python3 -m pip install  --user --upgrade pip
Successfully installed pip-20.0.1
root<strong i="14">@7d8107816f64</strong>:/# python3 -m pip --version
pip 20.0.1 from /root/.local/lib/python3.6/site-packages/pip (python 3.6)
root<strong i="15">@7d8107816f64</strong>:/# ls root/.local/bin/pip
pip     pip3    pip3.6
#Now we populate ~/.local/bin/
root<strong i="16">@7d8107816f64</strong>:/# python3 -m venv ~/.local
root<strong i="17">@7d8107816f64</strong>:/# ls root/.local/bin/
activate          activate.fish     easy_install-3.6  pip3              python
activate.csh      easy_install      pip               pip3.6            python3
root<strong i="18">@7d8107816f64</strong>:/# ./root/.local/bin/python --version
Python 3.6.9
root<strong i="19">@7d8107816f64</strong>:/# ./root/.local/bin/python -m pip install  --user --upgrade pip
ERROR: Can not perform a '--user' install. User site-packages are not visible in this virtualenv.

Portanto, se executarmos o executável .local/bin/python, não poderemos instalar o pip com --user

Oh, eu tinha perdido que você estava fazendo python3 -m venv ~/.local . É provável que isso confunda ferramentas como pip, porque ~/.local é o prefixo para instalações --user (no Linux). venvs e --user são duas maneiras _diferentes_ de instalar pacotes sem fazer alterações em todo o sistema: você deve usar um ou outro. Criar um venv em ~/.local faz um híbrido estranho dos dois.

O novo comportamento é presumivelmente conveniente para muitos, mas as instalações do 'usuário' me causaram algum sofrimento como desenvolvedor web - muitas vezes preciso preparar virtualenvs que serão implantados em nossas máquinas de produção e, se algum pacote estiver instalado na minha biblioteca de usuário, então, por padrão pip se recusará a instalá-lo no virtualenv que estou preparando e ainda sairá com sucesso . A notificação de que decidiu não instalar o pacote está enterrada dentro de 30 ou 40 páginas de saída do script que uso para preparar o virtualenv. O efeito final é que, uma vez que o virtualenv é implantado, os pacotes do meu diretório inicial não estão mais disponíveis, então alguns pacotes aleatórios estão faltando no meu aplicativo web de produção e ele cai morto.

Estou disposto a admitir que meu caso de uso não é o típico, então talvez isso ainda fosse uma boa ideia do ponto de vista geral de usabilidade.

Para outros que tiveram problemas semelhantes, existem algumas maneiras de contornar isso:

  • Adicione --force-reinstall a todas as suas linhas de comando pip install em scripts etc.
  • Exclua ~/.local/lib/python* e edite ~/.pip/pip.conf para adicionar user = no na seção global :
[global]
user = no
  • Faça algo mais drástico, como mudar ~/.local/lib para um arquivo ao invés de um diretório :smirk:

Como sempre, queridos mantenedores de embalagens, obrigado por tudo o que fazem - tenho certeza de que é praticamente impossível mudar qualquer coisa sem quebrar as coisas de alguém, e o fato de você continuar de qualquer maneira é realmente ótimo, porque nos permite progredir.

Ah, as instalações do usuário também podem causar grandes problemas em ambientes de integração contínua, onde muitas coisas diferentes são executadas na mesma conta de usuário, mas as pessoas ainda esperam que as compilações sejam isoladas umas das outras. Resolvemos isso tornando ~/.local somente leitura, mas as soluções acima provavelmente também funcionariam.

Quando você cria um virtualenv com as opções padrão, ele fica isolado: ele não pode ver os pacotes do site do usuário ou do sistema e, consequentemente, o pip deve funcionar apenas com os pacotes instalados no env. Isso se tornou o padrão há muitos anos, exatamente por causa dos tipos de problemas que você descreve.

Se você criar virtualenvs com a opção --system-site-packages (ou versões muito antigas do virtualenv onde esse era o padrão), eles agem como uma sobreposição nos pacotes que você instalaria, tanto em todo o sistema quanto em sua casa diretório. Se você quiser ter pacotes do sistema visíveis, mas não pacotes do usuário, você pode executar o Python com a opção -s ou a variável de ambiente PYTHONNOUSERSITE .

Oh! Sinto muito, você está totalmente certo. A política estranha de pacotes de site de sistema da minha organização ataca novamente. Obrigado por apontar algumas soluções.

Sem problemas. Os pacotes de site do sistema eram mais comuns há alguns anos, quando muitas vezes confiávamos nos gerenciadores de pacotes do sistema para coisas como numpy, então talvez valha a pena revisitar essa política. Mas ainda pode haver razões sensatas para usá-lo hoje.

Fechando de acordo com https://github.com/pypa/pip/issues/1668#issuecomment -544569965.

Muito obrigado @takluyver! ^>^

@takluyver Obrigado por resolver o problema que me incomoda há muito tempo
Mas notei que ao instalar pacotes com usuários não privilegiados, o Windows 10 python 3.8.2 com pip 20.0.2 ainda está falhando.

ERROR: Exception:
Traceback (most recent call last):
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\cli\base_command.py", line 186, in _main
    status = self.run(options, args)
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\commands\install.py", line 253, in run
    options.use_user_site = decide_user_install(
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\commands\install.py", line 604, in decide_user_install
    if site_packages_writable(root=root_path, isolated=isolated_mode):
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\commands\install.py", line 548, in site_packages_writable
    return all(
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\commands\install.py", line 549, in <genexpr>
    test_writable_dir(d) for d in set(get_lib_location_guesses(**kwargs))
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\utils\filesystem.py", line 140, in test_writable_dir
    return _test_writable_dir_win(path)
  File "c:\program files (x86)\python38-32\lib\site-packages\pip\_internal\utils\filesystem.py", line 153, in _test_writable_dir_win
    fd = os.open(file, os.O_RDWR | os.O_CREAT | os.O_EXCL)
PermissionError: [Errno 13] Permission denied: 'c:\\program files (x86)\\python38-32\\Lib\\site-packages\\accesstest_deleteme_fishfingers_custard_m59lch'

Eu pensei que isso poderia causar OSError de errno sendo errno.EACCES mas errno.EPERM .

@catPill , abra um novo problema para que possa ser rastreado corretamente. É perfeitamente plausível que eu tenha perdido algo no Windows.

Esta página foi útil?
0 / 5 - 0 avaliações