Instalando pacotes Python da pasta do sistema de arquivos local para o virtualenv com pip

346

É possível instalar pacotes usando o pip do sistema de arquivos local?

Eu executei o python setup.py sdistmeu pacote, que criou o arquivo tar.gz apropriado. Este arquivo está armazenado no meu sistema em /srv/pkg/mypackage/mypackage-0.1.0.tar.gz.

Agora, em um ambiente virtual, eu gostaria de instalar pacotes provenientes do pypi ou do local local específico /srv/pkg.

Isso é possível?

PS Eu sei que posso especificar pip install /srv/pkg/mypackage/mypackage-0.1.0.tar.gz. Isso funcionará, mas estou falando sobre o uso do /srv/pkglocal como outro local para o pip pesquisar se eu digitar pip install mypackage.

chadgh
fonte
Eu estava procurando instalar um pacote PyPi sem o setup.py, do WHL wheel, e ele foi instalado depois que eu baixei uma versão correta da minha versão do Python e executei pip install <Path-to-WHL-file>.
precisa saber é o seguinte

Respostas:

136

Tenho certeza de que o que você está procurando é chamado de --find-linksopção.

Embora você possa precisar gerar um dummy index.htmlpara o índice do pacote local, que lista os links para todos os pacotes. Essa ferramenta ajuda a:

https://github.com/wolever/pip2pi

Mikko Ohtamaa
fonte
100
pip install mypackage --no-index --find-links file:///srv/pkg/mypackageDeveria trabalhar.
jfs
11
Isso ajuda. E podemos usar a opção -i do pip para tratá-lo como um PyPI local.
Diabloneo
O comando easy_install equivalente é #easy_install --allow-hosts=None --find-links file:///srv/pkg/mypackage mypackage
Wilfred Hughes
Eu tive que criar um arquivo de distribuição de origem, não apenas apontá-lo para o diretório de projeto ou pacote antes que funcionasse. Isso me tropeçou. docs.python.org/3.6/distutils/sourcedist.html
Josh
3
Observe que --find-linksainda permitirá pesquisar no PyPI se o pacote não for encontrado no local especificado ou se uma versão mais recente estiver disponível. No Windows, acho que combinar isso com --only-binary=packagename(ou --only-binary=:all:) é extraordinariamente útil. Isso evita que o pip tente baixar quaisquer pacotes com dependências nativas que só têm distribuições de origem no PyPI (e, portanto, requerem compilação), que é o motivo mais comum para tentar instalar a partir de um diretório. Ao contrário --no-index, ainda posso instalar outros pacotes do PyPI.
Jpmc26
463

A respeito::

pip install --help
...
  -e, --editable <path/url>   Install a project in editable mode (i.e. setuptools
                              "develop mode") from a local project path or a VCS url.

por exemplo, pip install -e /srv/pkg

onde / srv / pkg é o diretório de nível superior onde 'setup.py' pode ser encontrado.

drpoo
fonte
49
Isso instalará o pacote no modo de desenvolvimento, o que significa que ele retornará apenas ao local onde estão as fontes. Se por algum motivo as fontes forem movidas ou excluídas, a importação do pacote falhará.
Trasplazio Garzuglio
3
@MarcoDinacci O interessante --editableé que parece procurar no diretório do pacote local e definir a fonte como um repositório git, se houver um - um pouco mais flexível do que apenas uma pasta. Não consigo encontrar documentação para isso.
precisa saber é o seguinte
3
Embora isso seja correto para a instalação de um pacote específico, especialmente um em desenvolvimento atual / intensivo em uma máquina local ou URL do VCS. Ele não responde à pergunta sobre procurar em um diretório pai por todas as fontes de pacotes locais, em oposição a uma fonte de pacote específica . A resposta aceita funciona quando você tem um diretório ou URL com vários pacotes dos quais deseja instalar o pip.
Gavin
@MarcoDinacci No entanto, vamos supor que um usuário faça o download do código. Eles colocam onde eles querem que o programa seja, se eles são tão inteligentes. Por que eles querem mudar isso?
Zelphir Kaltstahl
11
@ Simon existe uma maneira de dizer ao pip para não procurar um repositório git? Se eu fizer do pip install -eo check-out do código no git remote, gostaria de instalar o código como está (com alterações ainda não no controle remoto).
Pedru 27/01
39

Estou instalando pyfuzzymas não está no PyPI; ele retorna a mensagem: No matching distribution found for pyfuzzy.

Eu tentei a resposta aceita

pip install  --no-index --find-links=file:///Users/victor/Downloads/pyfuzzy-0.1.0 pyfuzzy

Mas também não funciona e retorna o seguinte erro:

Ignorando índices: https://pypi.python.org/simple Coletando pyfuzzy Não foi possível encontrar uma versão que atenda ao requisito pyfuzzy (das versões:) Nenhuma distribuição correspondente foi encontrada para pyfuzzy

Por fim, encontrei um bom caminho simples para isso: https://pip.pypa.io/en/latest/reference/pip_install.html

Install a particular source archive file.
$ pip install ./downloads/SomePackage-1.0.4.tar.gz
$ pip install http://my.package.repo/SomePackage-1.0.4.zip

Portanto, o seguinte comando funcionou para mim:

pip install ../pyfuzzy-0.1.0.tar.gz.

Espero que isso possa ajudar-lhe.

Victor Choy
fonte
4
Isso funcionou para mim. Tentei as outras abordagens e fui atropelado por Could not find a version that satisfieserro. Obrigado.
Rair
21

Esta é a solução que acabei usando:

import pip


def install(package):
    # Debugging
    # pip.main(["install", "--pre", "--upgrade", "--no-index",
    #         "--find-links=.", package, "--log-file", "log.txt", "-vv"])
    pip.main(["install", "--upgrade", "--no-index", "--find-links=.", package])


if __name__ == "__main__":
    install("mypackagename")
    raw_input("Press Enter to Exit...\n")

Eu juntei isso a partir dos exemplos de instalação do pip e da resposta de Rikard em outra pergunta . O argumento "--pre" permite instalar versões que não são de produção. O argumento "--no-index" evita pesquisar nos índices PyPI. O "--find-links =." pesquisas de argumento na pasta local (isso pode ser relativo ou absoluto). Eu usei os argumentos "--log-file", "log.txt" e "-vv" para depuração. O argumento "--upgrade" permite instalar versões mais recentes sobre as mais antigas.

Eu também encontrei uma boa maneira de desinstalá-los. Isso é útil quando você possui vários ambientes Python diferentes. É o mesmo formato básico, basta usar "uninstall" em vez de "install", com uma medida de segurança para evitar desinstalações não intencionais:

import pip


def uninstall(package):
    response = raw_input("Uninstall '%s'? [y/n]:\n" % package)
    if "y" in response.lower():
        # Debugging
        # pip.main(["uninstall", package, "-vv"])
        pip.main(["uninstall", package])
    pass


if __name__ == "__main__":
    uninstall("mypackagename")
    raw_input("Press Enter to Exit...\n")

A pasta local contém estes arquivos: install.py, uninstall.py, mypackagename-1.0.zip

Devan Williams
fonte
11
Obrigado. O "--find-links =." e "--no-index", onde a chave para colar um script python dentro do meu pacote de utilitários, que primeiro remove o pacote da versão antiga do site-packages e instala um pacote tar.gz'ed de um subdiretório da pasta package-utility (não sabia sobre --find-links =.), cria a roda e a instala. Tudo automatizado via plumbum e clique. Se alguém quiser, vou postar um link. Votado.
JackLeEmmerdeur
15

Uma opção --find-links faz o trabalho e funciona a partir do requirements.txtarquivo!

Você pode colocar arquivos de pacotes em alguma pasta e pegar o mais recente sem alterar o arquivo de requisitos, por exemplo requirements:

.
└───requirements.txt
└───requirements
    ├───foo_bar-0.1.5-py2.py3-none-any.whl
    ├───foo_bar-0.1.6-py2.py3-none-any.whl
    ├───wiz_bang-0.7-py2.py3-none-any.whl
    ├───wiz_bang-0.8-py2.py3-none-any.whl
    ├───base.txt
    ├───local.txt
    └───production.txt

Agora requirements/base.txtcolocado:

--find-links=requirements
foo_bar
wiz_bang>=0.8

Uma maneira elegante de atualizar pacotes proprietários, basta soltar um novo na pasta

Dessa maneira, você pode instalar pacotes de local folderAND pypicom a mesma chamada única:pip install -r requirements/production.txt

PS. Consulte o meu garfo cookiecutter-djangopackage para ver como dividir os requisitos e usar a organização de requisitos baseada em pastas.

Janusz Skonieczny
fonte
Obrigado, isso é ainda melhor do que eu estava pensando em fazer!
FoundNil
11

Na página de instalação de pacotes, você pode simplesmente executar:

pip instala / srv / pkg / mypackage

onde / srv / pkg / mypackage é o diretório que contém setup.py .


Além disso 1 , você pode instalá-lo a partir do arquivo morto:

pip install ./mypackage-1.0.4.tar.gz

1 Embora indicado na pergunta, devido à sua popularidade, ele também está incluído.

dim8
fonte
2
Essa deve ser a resposta padrão. Não há necessidade de procurar por pip com --find-links se você souber exatamente onde seu pacote está na máquina local.
Robert
6

Supondo que você possua virtualenv e um requirements.txtarquivo, é possível definir dentro deste arquivo onde obter os pacotes:

# Published pypi packages 
PyJWT==1.6.4
email_validator==1.0.3
# Remote GIT repo package, this will install as django-bootstrap-themes
git+https://github.com/marquicus/django-bootstrap-themes#egg=django-bootstrap-themes
# Local GIT repo package, this will install as django-knowledge
git+file:///soft/SANDBOX/python/django/forks/django-knowledge#egg=django-knowledge
marquicus
fonte
5

Tendo requisitos requirements.txteegg_dir como um diretório

você pode criar seu cache local:

$ pip download -r requirements.txt -d eggs_dir

então, usar esse "cache" é simples como:

$ pip install -r requirements.txt --find-links=eggs_dir

Sławomir Lenart
fonte
1

Para instalar apenas a partir do local, você precisa de 2 opções:

  • --find-links: onde procurar dependências. Não há necessidade defile:// prefixo mencionado por outros.
  • --no-index: não procure nos índices pypi por dependências ausentes (dependências não instaladas e não no --find-linkscaminho).

Assim, você pode executar de qualquer pasta o seguinte:

pip install --no-index --find-links /srv/pkg /path/to/mypackage-0.1.0.tar.gz

Se o seu mypackage estiver configurado corretamente, ele listará todas as suas dependências e, se você usou o pip download para baixar a cascata de dependências (ou seja, dependências de dependências, etc.), tudo funcionará.

Se você quiser usar o índice pypi, se estiver acessível, mas o fallback para as rodas locais, se não, poderá remover --no-indexe adicionar --retries 0. Você verá o pip pausar um pouco enquanto estiver tentando verificar o pypi em busca de uma dependência ausente (uma não instalada) e, quando encontrar que não pode alcançá-lo, voltará ao local. Não parece haver uma maneira de dizer ao pip para "procurar os locais primeiro e depois o índice".

Oliver
fonte
-1

Eu tenho tentado conseguir algo realmente simples e falhei miseravelmente, provavelmente sou estúpido.

De qualquer forma, se você possui um script / Dockerfileque baixa um arquivo zip de pacote python (por exemplo, do GitHub) e deseja instalá-lo, pode usar o file:///prefixo para instalá-lo, conforme mostrado no exemplo a seguir :

$ wget https://example.com/mypackage.zip
$ echo "${MYPACKAGE_MD5}  mypackage.zip" | md5sum --check -
$ pip install file:///.mypackage.zip

NOTA : Eu sei que você pode instalar o pacote imediatamente usando, pip install https://example.com/mypackage.zipmas no meu caso, eu queria verificar a soma de verificação (nunca paranóica o suficiente) e falhei miseravelmente ao tentar usar as várias opções fornecidas pelo pip / the#md5 fragmento.

Foi surpreendentemente frustrante fazer algo tão simples diretamente pip. Eu só queria passar uma soma de verificação e pipverificar se o zip estava correspondendo antes instalá-lo.

Eu provavelmente estava fazendo algo muito estúpido, mas no final desisti e optei por isso. Espero que ajude outras pessoas a tentar fazer algo semelhante.

Aldo 'xoen' Giambelluca
fonte