检查是否安装了 Python 包

在 Python 脚本中检查软件包是否安装的好方法是什么?我知道翻译很容易,但是我需要用脚本。

我想我可以检查系统上是否有一个在安装过程中创建的目录,但我觉得有一个更好的方法。我正在尝试确保 Skype 4Py 软件包已经安装,如果没有,我将安装它。

我完成检查的想法

  • 检查典型安装路径中的目录
  • 尝试导入包,如果抛出异常,则安装包
262132 次浏览

选项 # 2。如果抛出 ImportError,则未安装包(或未在 sys.path中安装)。

如果您指的是一个 Python 脚本,那么可以这样做:

Python 3.3 + use sys.module and 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")

巨蟒3:

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

巨蟒2:

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

最新答案

一个更好的方法是:

import subprocess
import sys


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

结果是:

print(installed_packages)


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

检查 requests是否已安装:

if 'requests' in installed_packages:
# Do something

为什么走这条路?有时会出现应用程序名称冲突。从应用程序名称空间导入并不能让您了解系统上安装了什么。

注意,这个提议的解决方案是有效的:

  • 当使用 pip 从 PyPI 或任何其他替代源(如 pip install http://some.site/package-name.zip或任何其他归档类型)安装时。
  • 当使用 python setup.py install手动安装时。
  • 从系统存储库安装时,如 sudo apt install python-requests

没有可能起作用的情况:

  • 在开发模式下安装时,如 python setup.py develop
  • 在开发模式下安装时,如 pip install -e /path/to/package/source/

旧答案

一个更好的方法是:

import pip
installed_packages = pip.get_installed_distributions()

对于 pip > = 10.x 使用:

from pip._internal.utils.misc import get_installed_distributions

为什么走这条路?有时会出现应用程序名称冲突。从应用程序名称空间导入并不能让您了解系统上安装了什么。

因此,您将获得 pkg_resources.Distribution对象的列表:

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)",
]

列一个清单:

flat_installed_packages = [package.project_name for package in installed_packages]


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

检查 requests是否已安装:

if 'requests' in flat_installed_packages:
# Do something

在 Python 3.3中,可以使用 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")

我想在这个主题上加入一些我的想法/发现。 我正在编写一个脚本来检查定制程序的所有需求。对于 Python 模块也有许多检查。

有点小问题

try:
import ..
except:
..

解决方案。 在我的示例中,一个名为 python-nmap的 python 模块,但是您将它与 import nmap一起导入,正如您看到的名称不匹配一样。因此,使用上述解决方案的测试返回 False 结果,并且它还在命中时导入模块,但是可能不需要为一个简单的测试/检查使用大量内存。

我还发现

import pip
installed_packages = pip.get_installed_distributions()

installed_packages将有 只有包是 安装了 pip。 在我的系统中,pip freeze返回 40 python 模块,而 installed_packages只有我手动安装的 1(python-nmap)。

下面的另一个解决方案,我知道它是 可能与问题无关,但我认为这是一个很好的做法,从一个执行的 保持测试功能独立安装,它可能是有用的一些。

对我有效的解决方案。它基于这个答案 如何在不导入 Python 模块的情况下检查它是否存在

from imp import find_module


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

注意: 这个解决方案也不能找到名为 python-nmap的模块,我只能使用 nmap(很容易使用) ,但是在这种情况下,模块不会被加载到内存中。

如果您希望从终端进行检查,可以运行

pip3 show package_name

如果没有返回任何内容,则不安装包。

如果您希望自动执行这个检查,例如,如果丢失了,您可以安装它,您的 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

如果您希望您的脚本安装缺少的包并继续执行,您可以这样做(在‘ python-krbV’包中的‘ 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))

作为 这个答案的延伸:

对于 Python2.* ,pip show <package_name>将执行相同的任务。

例如,pip show numpy将返回以下内容或类似内容:

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

您可以使用 setuptools 中的 pkg _ resources 模块,例如:

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)

请注意,python 模块和 python 包之间存在差异。包可以包含多个模块,模块名称可能与包名称不匹配。

一个快速的方法是使用 巨蟒命令行工具。 只需键入 import <your module name> 如果缺少模块,则会看到错误。

$ 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
$

嗯... ... 我看到的最方便的答案是使用命令行尝试导入。但我宁愿避免这种情况。

“ pip 冻结 | grep pkgname”怎么样?我试过了,效果很好。它还向您显示它的版本,以及它是在版本控制(安装)还是可编辑(开发)下安装的。

你可以用这个:

class myError(exception):
pass # Or do some thing like this.
try:
import mymodule
except ImportError as e:
raise myError("error was occurred")

在 Terminal 类型中

pip show some_package_name

例子

pip show matplotlib

打开命令提示符类型

pip3 list

我想评论@ice。更好的回复,但我不能,所以..。 我的观察是,带破折号的包是用下划线保存的,而不仅仅是像@dwich 注释中指出的那样用点保存

例如,你做 pip3 install sphinx-rtd-theme,但是:

  • importlib.util.find_spec(sphinx_rtd_theme)返回一个 Object
  • importlib.util.find_spec(sphinx-rtd-theme)返回无
  • 引发 ModuleNotFoundError

此外,一些名称完全改变。 例如,您执行 pip3 install pyyaml,但是它被简单地保存为 yaml

我用的是 python3.8

if pip list | grep -q \^'PACKAGENAME\s'
# installed ...
else
# not installed ...
fi

是否有机会使用下面给出的代码片段?当我运行这段代码时,它返回“模块熊猫没有安装”

a = "pandas"


try:
import a
print("module ",a," is installed")
except ModuleNotFoundError:
print("module ",a," is not installed")

但是当我运行下面给出的代码时:

try:
import pandas
print("module is installed")
except ModuleNotFoundError:
print("module is not installed")

它返回“模块熊猫已安装”。

他们之间有什么区别?

方法1

搜索包是否存在或不使用 Pip3列表命令

#**pip3 list** will display all the packages and **grep** command will search for a particular package
pip3 list | grep your_package_name_here

方法2

你可以使用 进口错误

try:
import your_package_name
except ImportError as error:
print(error,':( not found')

方法3

!pip install your_package_name
import your_package_name
...
...

我总是使用 Pylibcheck来检查是否安装了一个库,只需下载它通过做 pip install pylibcheck和可能是这样的

import pylibcheck


if not pylibcheck.checkPackage("mypackage"):
#not installed

它还支持元组和列表,因此您可以检查多个包,以及它们是否安装

import pylibcheck


packages = ["package1", "package2", "package3"]


if pylibcheck.checkPackage(packages):
#not installed

你也可以用它安装库,如果你想这样做,建议你检查官方 皮皮

使用 importlib.util.find_specsys.modules等技术和捕捉导入异常的顶级解决方案适用于大多数包,但在某些边缘情况下(如 beautifulsoup包)失败,因为导入中使用的包名与安装文件配置中使用的包名略有不同(本例中为 bs4)。对于这些边缘情况,除非您传递导入中使用的包名,而不是 requirements.txtpip安装中使用的包名,否则该解决方案无法工作。

对于我的用例,我需要编写一个基于 requirements.txt检查已安装包的包检查器,所以这个解决方案不起作用。我最后使用的是 subprocess.check显式调用 pip 模块来检查包的安装:

import subprocess


for pkg in packages:
try:
subprocess.check_output('py -m pip show ' + pkg)
except subprocess.CalledProcessError as ex:
not_found.append(pkg)

它比其他方法稍慢一些,但是更可靠,并且可以处理边缘情况。