Check if Python Package is installed
Asked Answered
S

21

179

What's a good way to check if a package is installed while within a Python script? I know it's easy from the interpreter, but I need to do it within a script.

I guess I could check if there's a directory on the system that's created during the installation, but I feel like there's a better way. I'm trying to make sure the Skype4Py package is installed, and if not I'll install it.

My ideas for accomplishing the check

  • check for a directory in the typical install path
  • try to import the package and if an exception is throw, then install package
Selfjustifying answered 26/6, 2009 at 20:54 Comment(1)
Writing a Python script to automate starting Skype and using tcpdump to collect packet data so I can analyze how the network functions when you have a conference call.Selfjustifying
S
161

If you mean a python script, just do something like this:

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

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.
Spradling answered 26/6, 2009 at 21:0 Comment(9)
Warning: I just had a situation today where the ImportError was thrown within the module itself. This should not happen often, but just be aware that this check is not reliable in all cases.Lenhard
This doesn't only check; it also imports it; see also #14050781Submiss
Yes. That's generally what you want. You can use the import tools module to do a more sophisticated check, but most of the time the only reason you care if a module is installed is because you want to use it.Spradling
This will fail if you have another file with the same name as the package.Botts
Sure, but that's a completely different problem. If you have two different modules or packages with the same name in your lookup path you are in trouble.Spradling
@Spradling there's a := operator in the elif clause and I'm puzzled about it, because it throws a SyntaxError: invalid syntax at the double dot and I double checked to confirm that there's no such operator in python. Is there a little typo? I tried direct assignment (=) and it doesn't work either, but it might be an obvious thing I don't see, as I still count myself a python beginner.Ichang
@Ichang That's a new walrus operator: docs.python.org/3/whatsnew/3.8.htmlClevelandclevenger
@Clevelandclevenger Ah, thanks a lot, that explains the issue! I'm on 3.7.Ichang
None of the above methods worked for the package beautifulsoup4! It neither showed up in importlib's find_spec, nor in sys.modules even if the package was installed.Erik
R
101

As of Python 3.3, you can use the find_spec() method

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")
Rotifer answered 23/1, 2017 at 21:23 Comment(2)
Clean and simple, best answer here. This needs more upvotes.Rowden
Be careful. If package name contains dashes, find_spec() cannot find it unless you use dots. Example: importlib.util.find_spec('google-cloud-logging') finds nothing while importlib.util.find_spec('google.cloud.logging') is found. The official name and name that pip shows is with dashes, not dots. Might be confusing therefore use with caution.Aedes
T
68

Updated answer

A better way of doing this is:

import subprocess
import sys

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

The result:

print(installed_packages)

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

Check if requests is installed:

if 'requests' in installed_packages:
    # Do something

Why this way? Sometimes you have app name collisions. Importing from the app namespace doesn't give you the full picture of what's installed on the system.

Note, that proposed solution works:

  • When using pip to install from PyPI or from any other alternative source (like pip install http://some.site/package-name.zip or any other archive type).
  • When installing manually using python setup.py install.
  • When installing from system repositories, like sudo apt install python-requests.

Cases when it might not work:

  • When installing in development mode, like python setup.py develop.
  • When installing in development mode, like pip install -e /path/to/package/source/.

Old answer

A better way of doing this is:

import pip
installed_packages = pip.get_installed_distributions()

For pip>=10.x use:

from pip._internal.utils.misc import get_installed_distributions

Why this way? Sometimes you have app name collisions. Importing from the app namespace doesn't give you the full picture of what's installed on the system.

As a result, you get a list of pkg_resources.Distribution objects. See the following as an example:

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

Make a list of it:

flat_installed_packages = [package.project_name for package in installed_packages]

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

Check if requests is installed:

if 'requests' in flat_installed_packages:
    # Do something
Twister answered 16/12, 2014 at 1:29 Comment(20)
As mentioned in the other answer, it is possible that the error is not caught. Therefore I think this should be the accepted answer.Rhinitis
AttributeError: module 'pip' has no attribute 'get_installed_distributions'Scarificator
Probably it was take out from most recent version of pip. Which version are you using? I think in 8.x it still worked.Twister
I'm using 10.0.1 here. pip's own manual also advises against importing pip or using any of it's methods: "As noted previously, pip is a command line program. While it is implemented in Python, and so is available from your Python code via import pip, you must not use pip's internal APIs in this way."Scarificator
This works indeed (for now). It should be noted however that pip itself uses against doing this.Scarificator
Regarding what's written in the pip's own manual. It's very arguable. My vision. Pip is the tool used for installing the packages. It knows about the versions. On the other hand, namespaces in python are not uniqe. Two packages like "django-something" and "python-something" might have the same "something" as source root. Famous example of such is "django-simple-captcha" and "django-recaptcha". Both use "captcha" as source root. Both are written for django and have similar structure, still different. My question, why not to use the best tool that knows things well?Twister
In addition, as far as I understand from their arguments not to use pip in other way than command line, is mainly that devs shouldn't use pip to modify/write things (as they say, it's not thread safe). However, checking whether package is installed, is simply reading, which is harmless.Twister
@NicoSchlömer: Fair enough, see my new updated answer. :)Twister
This method does not work with packages such as 'json' (returns False when import json is indeed working). The method of ice.nicer is working in this case.Miosis
@mountrix: Why would you check for availability of json? It's a part of a standard library. Therefore, irrelevant.Twister
@ArturBarseghyan but would'nt be nice to have a function returning False when the package is really not available, so it would require an installation?Miosis
@mountrix: For checking if a given Python package is installed the above given example is sufficient. If you want to check whether a certain standard library package is included in your Python distribution, you should use try/except or use third-party tools such as python-stdlib-list.readthedocs.ioTwister
This assumes that your runtime has pip installed. That is not a safe assumption.Spradling
@Christopher: True. Especially, if you're using MicroPython, CircuitPython or some other non-standard distributions (such as Jython), it won't work. So, if you somehow have situation, where you download all packages manually and for each of them do python setup.py install or use easy_install - it won't work either. However, all modern alternative Python package managers, include pip.Twister
Somehow I needed to use the check if "u'requests'" in installed_packages: from Updated Answer to work for me. The output of print() produces this on my macOS python: [..., u'pytz', u'requests', ...]Bills
@Buju: What version of Python do you use? 'requests' in installed_packages does work for me on Python 2.7, 3.4, 3.5, 3.6 and 3.7. I'm curious which version of Python do you use.Twister
@ArturBarseghyan I'm on Python 2.7.10 (macOS system python) ... actually I have to use if "requests'" (notice the single quote at the end). doesn't make sense at all.Bills
@Buju: That's really strange. I'll update the answer and add MacOS section. Thank you!Twister
This doesn't answer the question: "is package 'x' installed?". There are many ways to install a package without using pip. E.g., you can make and install a package from source. This answer won't find those. The answer from @Rotifer about find_spec() is right.Cyclostyle
@Arthur: Please list all the many ways to install Python packages and clearly indicate all uses-cases, where solution I propose does not work. For the record, it does work in the following cases: (a) When using pip to install from PyPI or from any other alternative source (like pip install http://some.site/package-name.zip or any other archive type). (b) When installing manually using python setup.py install. (c) When installing from system repositories, like sudo apt install python-requests. I know only one case when it does not work: python setup.py develop.Twister
S
43

If you want to have the check from the terminal, you can run

pip3 show package_name

and if nothing is returned, the package is not installed.

If perhaps you want to automate this check, so that for example you can install it if missing, you can have the following in your bash script:

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
Schwitzer answered 19/9, 2017 at 14:31 Comment(3)
This seems great but it always returns "Not Installed" for me. Why?Univalence
Can you share the output of the “$pip3 —version” and “$pip3 show package_name”, where you replace package_name with the desired package?Schwitzer
Shell tip: you can use if to directly test a successful command: if pip3 show package_name 1>/dev/null; then ...Fleeting
P
15

Open your command prompt type

pip3 list
Penelope answered 10/3, 2020 at 14:59 Comment(0)
S
8

In the Terminal type

pip show some_package_name

Example

pip show matplotlib
Shainashaine answered 22/2, 2020 at 20:27 Comment(0)
T
6

As an extension of this answer:

For Python 2.*, pip show <package_name> will perform the same task.

For example pip show numpy will return the following or alike:

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: [email protected]
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
Tetragram answered 5/7, 2018 at 7:23 Comment(1)
Not from a script but great for command line checking. ThanksWoodpile
C
5

You can use the pkg_resources module from setuptools. For example:

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)

Note that there is a difference between python module and a python package. A package can contain multiple modules and module's names might not match the package name.

Cognation answered 20/8, 2018 at 13:24 Comment(1)
Yes, the package vs. module distinction can be quite important. For example both python-magic and file-magic provide modules named magic but their interfaces are incompatible with each other. Also in 3.8 importlib.metadata was added and imho it's rather handy.Angloirish
B
4
if pip list | grep -q \^'PACKAGENAME\s'
  # installed ...
else
  # not installed ...
fi
Botts answered 21/7, 2020 at 16:54 Comment(0)
E
4

Method 1

to search weather a package exists or not use pip3 list command

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

Method 2

You can use ImportError

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

Method 3

!pip install your_package_name
import your_package_name
...
...
Epididymis answered 2/1, 2022 at 5:27 Comment(0)
J
2

You can use this:

class myError(exception):
 pass # Or do some thing like this.
try:
 import mymodule
except ImportError as e:
 raise myError("error was occurred")
Judah answered 1/12, 2019 at 17:42 Comment(1)
Unless you have a file with the same name.Botts
C
1

I'd like to add some thoughts/findings of mine to this topic. I'm writing a script that checks all requirements for a custom made program. There are many checks with python modules too.

There's a little issue with the

try:
   import ..
except:
   ..

solution. In my case one of the python modules called python-nmap, but you import it with import nmap and as you see the names mismatch. Therefore the test with the above solution returns a False result, and it also imports the module on hit, but maybe no need to use a lot of memory for a simple test/check.

I also found that

import pip
installed_packages = pip.get_installed_distributions()

installed_packages will have only the packages has been installed with pip. On my system pip freeze returns over 40 python modules, while installed_packages has only 1, the one I installed manually (python-nmap).

Another solution below that I know it may not relevant to the question, but I think it's a good practice to keep the test function separate from the one that performs the install it might be useful for some.

The solution that worked for me. It based on this answer 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

NOTE: this solution can't find the module by the name python-nmap too, I have to use nmap instead (easy to live with) but in this case the module won't be loaded to the memory whatsoever.

Chitarrone answered 7/9, 2017 at 12:4 Comment(0)
P
1

I would like to comment to @ice.nicer reply but I cannot, so ... My observations is that packages with dashes are saved with underscores, not only with dots as pointed out by @dwich comment

For example, you do pip3 install sphinx-rtd-theme, but:

  • importlib.util.find_spec(sphinx_rtd_theme) returns an Object
  • importlib.util.find_spec(sphinx-rtd-theme) returns None
  • importlib.util.find_spec(sphinx.rtd.theme) raises ModuleNotFoundError

Moreover, some names are totally changed. For example, you do pip3 install pyyaml but it is saved simply as yaml

I am using python3.8

Poll answered 29/5, 2020 at 20:8 Comment(0)
G
0

If you'd like your script to install missing packages and continue, you could do something like this (on example of 'krbV' module in 'python-krbV' package):

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))
Grozny answered 2/2, 2018 at 13:5 Comment(0)
J
0

A quick way is to use python command line tool. Simply type import <your module name> You see an error if module is missing.

$ 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
$
Jedidiah answered 20/9, 2018 at 1:2 Comment(0)
G
0

Hmmm ... the closest I saw to a convenient answer was using the command line to try the import. But I prefer to even avoid that.

How about 'pip freeze | grep pkgname'? I tried it and it works well. It also shows you the version it has and whether it is installed under version control (install) or editable (develop).

Gpo answered 7/10, 2019 at 21:4 Comment(0)
P
0

I've always used pylibcheck to check if a lib is installed or not, simply download it by doing pip install pylibcheck and the could could be like this

import pylibcheck

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

it also supports tuples and lists so you can check multiple packages and if they are installed or not

import pylibcheck

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

if pylibcheck.checkPackage(packages):
     #not installed

you can also install libs with it if you want to do that, recommend you check the official pypi

Pelt answered 11/3, 2022 at 19:44 Comment(0)
E
0

The top voted solution which uses techniques like importlib.util.find_spec and sys.modules and catching import exceptions works for most packages but fails in some edge cases (such as the beautifulsoup package) where the package name used in imports is somewhat different (bs4 in this case) than the one used in setup file configuration. For these edge cases, this solution doesn't work unless you pass the package name used in imports instead of the one used in requirements.txt or pip installations.

For my use case, I needed to write a package checker that checks installed packages based on requirements.txt, so this solution didn't work. What I ended up using was subprocess.check to call the pip module explicitly to check for the package installation:

import subprocess

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

It's a bit slower than the other methods but more reliable and handles the edge cases.

Erik answered 19/10, 2022 at 8:47 Comment(0)
B
0

While not perfect, the following solution is usually much quicker than pip show ... and also works for multiple packages

_pip_install() {
    installed_packages=$(pip freeze)

    for PACKAGE in "$@"; do
        if echo "$installed_packages" | grep "^${PACKAGE}=="; then
            true
        else
            echo "Installing $PACKAGE..."
            pip install "$PACKAGE"
        fi
    done
}
Beneficent answered 14/8, 2023 at 22:4 Comment(0)
L
-1

Go option #2. If ImportError is thrown, then the package is not installed (or not in sys.path).

Loewi answered 26/6, 2009 at 20:59 Comment(0)
A
-1

Is there any chance to use the snippets given below? When I run this code, it returns "module pandas is not installed"

a = "pandas"

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

But when I run the code given below:

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

It returns "module pandas is installed".

What is the difference between them?

Alexandros answered 31/1, 2021 at 6:14 Comment(1)
Create your own question instead of asking in an answer to another question. But as an answer, in the first one, when you do import a, you are literally looking for a module called 'a'. It's not using your variable. If you want to use variable package names, you'll need to use libraries like importlib.import_module() or something similar.Brinson

© 2022 - 2024 — McMap. All rights reserved.