【问题标题】:Check if Python Package is installed检查是否安装了 Python 包
【发布时间】:2010-11-06 06:43:23
【问题描述】:

在 Python 脚本中检查是否安装了包的好方法是什么?我知道解释器很容易,但我需要在脚本中完成。

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

我对完成检查的想法

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

【问题讨论】:

  • 编写 Python 脚本自动启动 Skype 并使用 tcpdump 收集数据包数据,以便我可以在您召开电话会议时分析网络的运行情况。

标签: python package skype python-import


【解决方案1】:

如果你的意思是一个 python 脚本,只需执行以下操作:

Python 3.3+ 使用 sys.modules 和 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.

【讨论】:

  • 警告:我今天遇到了一个情况,在模块本身中抛出了 ImportError。这种情况不应该经常发生,但请注意,这种检查并非在所有情况下都可靠。
  • 这不仅仅是检查;它也进口它;另见stackoverflow.com/questions/14050281/…
  • 是的。这通常是你想要的。您可以使用导入工具模块进行更复杂的检查,但大多数时候您关心模块是否已安装的唯一原因是您想使用它。
  • 当然,但这是一个完全不同的问题。如果您的查找路径中有两个不同的模块或同名的包,那么您就有麻烦了。
  • @Oak_3260548 这是一个新的海象运算符:docs.python.org/3/whatsnew/3.8.html
【解决方案2】:

更新答案

一个更好的方法是:

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

【讨论】:

  • 如另一个答案中所述,错误可能未被捕获。因此,我认为这应该是公认的答案。
  • 此方法不适用于 'json' 等包(import json 确实有效时返回 False)。在这种情况下,ice.nicer 的方法是有效的。
  • 不知何故我需要使用更新答案中的检查if "u'requests'" in installed_packages: 为我工作。 print() 的输出在我的 macOS python 上产生:[..., u'pytz', u'requests', ...]
  • @ArturBarseghyan 我使用的是 Python 2.7.10(macOS 系统 python)...实际上我必须使用 if "requests'"(注意末尾的单引号)。完全没有意义。
  • 这没有回答问题:“是否安装了包'x'?”。有很多方法可以在不使用pip 的情况下安装软件包。例如,您可以从源代码制作和安装软件包。这个答案不会找到那些。 @ice.nicer 关于find_spec() 的回答是正确的。
【解决方案3】:

从 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")

【讨论】:

  • 干净简单,最佳答案在这里。这需要更多的支持。
  • 小心。如果包名称包含破折号,除非您使用点,否则 find_spec() 无法找到它。示例:importlib.util.find_spec('google-cloud-logging') 在找到 importlib.util.find_spec('google.cloud.logging') 时什么也找不到。 pip 显示的官方名称和名称是破折号,而不是圆点。可能会造成混淆,因此请谨慎使用。
【解决方案4】:

如果你想从终端检查,你可以运行

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

【讨论】:

  • 这看起来不错,但它总是为我返回“未安装”。为什么?
  • 您能否分享“$pip3 —version”和“$pip3 show package_name”的输出,您将 package_name 替换为所需的包?
  • Shell提示:可以使用if直接测试成功命令:if pip3 show package_name 1>/dev/null; then ...
【解决方案5】:

作为this answer的扩展:

对于 Python 2.*,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

【讨论】:

  • 不是来自脚本,但非常适合命令行检查。谢谢
【解决方案6】:

打开你的命令提示符类型

pip3 list

【讨论】:

    【解决方案7】:

    您可以使用 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 包之间存在差异。一个包可以包含多个模块,并且模块的名称可能与包名称不匹配。

    【讨论】:

      【解决方案8】:

      在终端类型中

      pip show some_package_name
      

      例子

      pip show matplotlib
      

      【讨论】:

        【解决方案9】:
        if pip list | grep -q \^'PACKAGENAME\s'
          # installed ...
        else
          # not installed ...
        fi
        

        【讨论】:

          【解决方案10】:

          你可以用这个:

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

          【讨论】:

          • 除非你有同名的文件。
          【解决方案11】:

          我想在这个主题中添加一些我的想法/发现。 我正在编写一个脚本来检查定制程序的所有要求。 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)。

          我知道下面的另一种解决方案可能与问题无关,但我认为将测试功能与执行测试功能分开是一个好习惯安装它可能对某些人有用。

          对我有用的解决方案。它基于这个答案How to check if a python module exists without importing it

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

          注意:此解决方案也找不到名称为 python-nmap 的模块,我必须改用 nmap(易于使用)但在这种情况下,模块不会加载到内存中.

          【讨论】:

            【解决方案12】:

            方法一

            使用 pip3 list 命令搜索是否存在包的天气

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

            方法二

            您可以使用 ImportError

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

            方法3

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

            【讨论】:

              【解决方案13】:

              如果您希望脚本安装缺少的包并继续,您可以执行以下操作(以“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))
              

              【讨论】:

                【解决方案14】:

                一个快速的方法是使用 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
                $
                

                【讨论】:

                  【解决方案15】:

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

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

                  【讨论】:

                    【解决方案16】:

                    我想对@ice.nicer 的回复发表评论,但我不能,所以... 我的观察是,带有破折号的包用下划线保存,而不仅仅是@dwich 评论指出的点

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

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

                    此外,有些名称完全改变了。 例如,您使用pip3 install pyyaml,但它被简单地保存为yaml

                    我用的是python3.8

                    【讨论】:

                      【解决方案17】:

                      选择 #2。如果抛出ImportError,则说明包没有安装(或不在sys.path中)。

                      【讨论】:

                        【解决方案18】:

                        有没有机会使用下面给出的sn-ps?当我运行此代码时,它返回“未安装模块熊猫”

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

                        它返回“模块 pandas 已安装”。

                        它们有什么区别?

                        【讨论】:

                        • 创建您自己的问题,而不是回答另一个问题。但作为答案,在第一个中,当您执行import a 时,您实际上是在寻找一个名为“a”的模块。它没有使用您的变量。如果要使用变量包名称,则需要使用 importlib.import_module() 之类的库或类似名称。
                        猜你喜欢
                        • 2021-11-23
                        • 2013-03-23
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-10-01
                        • 2015-03-06
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多