Verifique se o pacote Python está instalado


112

Qual é uma boa maneira de verificar se um pacote está instalado dentro de um script Python? Sei que é fácil para o intérprete, mas preciso fazer isso dentro de um script.

Acho que poderia verificar se há um diretório no sistema que foi criado durante a instalação, mas acho que há uma maneira melhor. Estou tentando ter certeza de que o pacote Skype4Py está instalado, caso contrário, irei instalá-lo.

Minhas ideias para realizar a verificação

  • verifique se há um diretório no caminho de instalação típico
  • tente importar o pacote e se uma exceção for lançada, então instale o pacote

Escrever um script Python para automatizar a inicialização do Skype e usar tcpdump para coletar dados de pacote para que eu possa analisar como a rede funciona quando você tem uma chamada em conferência.
Kevin

Respostas:


107

Se você se refere a um script Python, faça algo assim:

Python 3.3+ usa sys.modules e find_spec :

import importlib.util
import sys

# For illustrative purposes.
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # If you choose to perform the actual import ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

Python 3:

try:
    import mymodule
except ImportError as e:
    pass  # module doesn't exist, deal with it.

Python 2:

try:
    import mymodule
except ImportError, e:
    pass  # module doesn't exist, deal with it.

6
Aviso: Tive uma situação hoje em que ImportError foi lançado dentro do próprio módulo. Isso não deve acontecer com frequência, mas esteja ciente de que essa verificação não é confiável em todos os casos.
Koen Bok

7
Isso não apenas verifica ; também o importa; veja também stackoverflow.com/questions/14050281/…
Jorge Leitao

6
Sim. Geralmente é isso que você deseja. Você pode usar o módulo de ferramentas de importação para fazer uma verificação mais sofisticada, mas na maioria das vezes a única razão pela qual você se importa se um módulo está instalado é porque você deseja usá-lo.
Christopher

Isso falhará se você tiver outro arquivo com o mesmo nome do pacote.
Sapphire_Brick

Claro, mas esse é um problema completamente diferente. Se você tiver dois módulos ou pacotes diferentes com o mesmo nome em seu caminho de pesquisa, você está com problemas.
Christopher

56

Resposta atualizada

A melhor maneira de fazer isso é:

import subprocess
import sys

reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]

O resultado:

print(installed_packages)

[
    "Django",
    "six",
    "requests",
]

Verifique se requestsestá instalado:

if 'requests' in installed_packages:
    # Do something

Por que assim? Às vezes, você tem conflitos de nomes de aplicativos. Importar do namespace do aplicativo não fornece uma imagem completa do que está instalado no sistema.

Observe que a solução proposta funciona:

  • Ao usar o pip para instalar a partir do PyPI ou de qualquer outra fonte alternativa (como pip install http://some.site/package-name.zipou qualquer outro tipo de arquivo).
  • Ao instalar manualmente usando python setup.py install.
  • Ao instalar a partir de repositórios do sistema, como sudo apt install python-requests.

Casos em que pode não funcionar:

  • Ao instalar em modo de desenvolvimento, como python setup.py develop.
  • Ao instalar em modo de desenvolvimento, como pip install -e /path/to/package/source/.

Resposta antiga

A melhor maneira de fazer isso é:

import pip
installed_packages = pip.get_installed_distributions()

Para pip> = 10.x, use:

from pip._internal.utils.misc import get_installed_distributions

Por que assim? Às vezes, você tem conflitos de nomes de aplicativos. Importar do namespace do aplicativo não fornece uma imagem completa do que está instalado no sistema.

Como resultado, você obtém uma lista de pkg_resources.Distributionobjetos. Veja o seguinte como exemplo:

print installed_packages
[
    "Django 1.6.4 (/path-to-your-env/lib/python2.7/site-packages)",
    "six 1.6.1 (/path-to-your-env/lib/python2.7/site-packages)",
    "requests 2.5.0 (/path-to-your-env/lib/python2.7/site-packages)",
]

Faça uma lista disso:

flat_installed_packages = [package.project_name for package in installed_packages]

[
    "Django",
    "six",
    "requests",
]

Verifique se requestsestá instalado:

if 'requests' in flat_installed_packages:
    # Do something

2
Conforme mencionado na outra resposta, é possível que o erro não seja detectado. Portanto, acho que essa deve ser a resposta aceita.
Jorrick Sleijster de

1
Este método não funciona com pacotes como 'json' (retorna False quando import jsonestá realmente funcionando). O método de ice.nicer está funcionando neste caso.
mountrix

1
De alguma forma, eu precisava usar a verificação if "u'requests'" in installed_packages:da Resposta atualizada para trabalhar para mim. A saída de print()produz isso no meu macOS python:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan Estou no Python 2.7.10 (macOS system python) ... na verdade, tenho que usar if "requests'"(observe a aspa simples no final). não faz sentido algum.
Buju

1
Isso não responde à pergunta: "o pacote 'x' está instalado?". Existem muitas maneiras de instalar um pacote sem usar pip. Por exemplo, você pode fazer e instalar um pacote do código-fonte. Esta resposta não os encontrará. A resposta de @ ice.nicer sobre find_spec()está certa.
Arthur

43

A partir do Python 3.3, você pode usar o método find_spec ()

import importlib.util

# For illustrative purposes.
package_name = 'pandas'

spec = importlib.util.find_spec(package_name)
if spec is None:
    print(package_name +" is not installed")

4
Limpo e simples, a melhor resposta aqui. Isso precisa de mais votos positivos.
David Parks,

5
Seja cuidadoso. Se o nome do pacote contém travessões, find_spec () não pode localizá-lo a menos que você use pontos. Exemplo: importlib.util.find_spec('google-cloud-logging')não encontra nada enquanto importlib.util.find_spec('google.cloud.logging')for encontrado. O nome oficial e o nome que pip mostra são traços, não pontos. Pode ser confuso, portanto, use com cuidado.
dwich

27

Se você quiser ter a verificação do terminal, você pode executar

pip3 show package_name

e se nada for retornado, o pacote não está instalado.

Se talvez você queira automatizar essa verificação, de forma que, por exemplo, você possa instalá-la se estiver faltando, você pode ter o seguinte em seu script bash:

pip3 show package_name 1>/dev/null #pip for Python 2
if [ $? == 0 ]; then
   echo "Installed" #Replace with your actions
else
   echo "Not Installed" #Replace with your actions, 'pip3 install --upgrade package_name' ?
fi

Isso parece ótimo, mas sempre retorna "Não instalado" para mim. Por quê?
Elliptica

Você pode compartilhar a saída de “$ pip3 —version” e “$ pip3 show package_name”, onde você substitui package_name pelo pacote desejado?
Ognjen Vukovic

Dica de shell: você pode usar ifpara testar diretamente um comando bem-sucedido:if pip3 show package_name 1>/dev/null; then ...
MestreLion

6

Como uma extensão desta resposta :

Para Python 2. *, pip show <package_name>executará a mesma tarefa.

Por exemplo pip show numpy, retornará o seguinte ou algo semelhante:

Name: numpy
Version: 1.11.1
Summary: NumPy: array processing for numbers, strings, records, and objects.
Home-page: http://www.numpy.org
Author: NumPy Developers
Author-email: numpy-discussion@scipy.org
License: BSD
Location: /home/***/anaconda2/lib/python2.7/site-packages
Requires: 
Required-by: smop, pandas, tables, spectrum, seaborn, patsy, odo, numpy-stl, numba, nfft, netCDF4, MDAnalysis, matplotlib, h5py, GridDataFormats, dynd, datashape, Bottleneck, blaze, astropy

Não de um script, mas ótimo para verificação de linha de comando. Obrigado
Jj Rivero

3

Você pode usar o módulo pkg_resources do setuptools. Por exemplo:

import pkg_resources

package_name = 'cool_package'
try:
    cool_package_dist_info = pkg_resources.get_distribution(package_name)
except pkg_resources.DistributionNotFound:
    print('{} not installed'.format(package_name))
else:
    print(cool_package_dist_info)

Observe que há uma diferença entre o módulo python e um pacote python. Um pacote pode conter vários módulos e os nomes dos módulos podem não corresponder ao nome do pacote.



1

Eu gostaria de adicionar algumas idéias / descobertas minhas a este tópico. Estou escrevendo um script que verifica todos os requisitos de um programa personalizado. Existem muitas verificações com módulos python também.

Há um pequeno problema com o

try:
   import ..
except:
   ..

solução. No meu caso, um dos módulos python foi chamado python-nmap, mas você o importa com import nmape como vê os nomes incompatíveis. Portanto, o teste com a solução acima retorna um resultado False e também importa o módulo ao acertar, mas talvez não seja necessário usar muita memória para um teste / verificação simples.

Eu também descobri que

import pip
installed_packages = pip.get_installed_distributions()

installed_packagesterá apenas os pacotes que foram instalados com pip . No meu sistema pip freezeretorna sobre 40módulos python, enquanto installed_packagestem apenas 1, o que instalei manualmente (python-nmap).

Outra solução abaixo que eu sei que pode não ser relevante para a questão , mas acho uma boa prática manter a função de teste separada daquela que executa a instalação, ela pode ser útil para alguns.

A solução que funcionou para mim. É com base nesta resposta como verificar se existe um módulo python sem importá-lo

from imp import find_module

def checkPythonmod(mod):
    try:
        op = find_module(mod)
        return True
    except ImportError:
        return False

NOTA: esta solução também não consegue encontrar o módulo pelo nome python-nmap, eu tenho que usar no nmaplugar (fácil de conviver), mas neste caso o módulo não será carregado na memória de forma alguma.


0

Se quiser que seu script instale os pacotes ausentes e continue, você pode fazer algo assim (no exemplo do módulo 'krbV' no pacote 'python-krbV'):

import pip
import sys

for m, pkg in [('krbV', 'python-krbV')]:
    try:
        setattr(sys.modules[__name__], m, __import__(m))
    except ImportError:
        pip.main(['install', pkg])
        setattr(sys.modules[__name__], m, __import__(m))

0

Uma maneira rápida é usar a ferramenta de linha de comando python . Basta digitar. import <your module name> Você verá um erro se o módulo estiver ausente.

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
>>> import sys
>>> import jocker
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named jocker
$

0

Hmmm ... o mais próximo que vi de uma resposta conveniente foi usar a linha de comando para tentar a importação. Mas prefiro até evitar isso.

Que tal 'pip freeze | grep pkgname '? Eu tentei e funciona bem. Também mostra a versão que possui e se está instalado sob controle de versão (instalar) ou editável (desenvolver).


0

class myError (exceção): pass #ou faça alguma coisa tente: import mymodule exceto ImportError as e: raise myError ("ocorreu um erro")


0

No tipo de Terminal

pip show some_package_name

Exemplo

pip show matplotlib

0

Eu gostaria de comentar a resposta de @ ice.nicer, mas não posso, então ... Minhas observações são que pacotes com traços são salvos com sublinhados, não apenas com pontos, como apontado pelo comentário de @dwich

Por exemplo, você faz pip3 install sphinx-rtd-theme, mas:

  • importlib.util.find_spec(sphinx_rtd_theme) retorna um objeto
  • importlib.util.find_spec(sphinx-rtd-theme) retorna nenhum
  • importlib.util.find_spec(sphinx.rtd.theme) levanta ModuleNotFoundError

Além disso, alguns nomes são totalmente alterados. Por exemplo, você faz, pip3 install pyyamlmas é salvo simplesmente comoyaml

Estou usando o python3.8


0
if pip3 list | grep -sE '^some_command\s+[0-9]' >/dev/null
  # installed ...
else
  # not installed ...
fi

-1

Vá para a opção nº 2. Se ImportErrorfor lançado, o pacote não está instalado (ou não está sys.path).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.