169

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
Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
Kevin
  • 2,361
  • 2
  • 20
  • 20
  • 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. – Kevin Jun 26 '09 at 21:03

21 Answers21

154

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.
Christopher
  • 8,815
  • 2
  • 32
  • 41
  • 11
    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. – Koen Bok Jun 26 '09 at 21:07
  • 8
    This doesn't only *check*; it also imports it; see also http://stackoverflow.com/questions/14050281/how-to-check-if-a-python-module-exists-without-importing-it – Jorge Leitao Nov 15 '14 at 08:49
  • 8
    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. – Christopher Jan 23 '15 at 18:30
  • This will fail if you have another file with the same name as the package. – Sapphire_Brick Jul 21 '20 at 16:15
  • 1
    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. – Christopher Aug 05 '20 at 17:13
  • @Christopher 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. – Oak_3260548 Dec 21 '20 at 08:58
  • 1
    @Oak_3260548 That's a new walrus operator: https://docs.python.org/3/whatsnew/3.8.html – Pugsley Jan 10 '21 at 18:51
  • @Pugsley Ah, thanks a lot, that explains the issue! I'm on 3.7. – Oak_3260548 Jan 10 '21 at 20:43
  • 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. – Prahlad Yeri Oct 19 '22 at 07:59
93

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")
Arthur
  • 525
  • 7
  • 18
ice.nicer
  • 1,644
  • 14
  • 13
  • 7
    Clean and simple, best answer here. This needs more upvotes. – David Parks Mar 08 '19 at 03:56
  • 13
    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. – dwich May 07 '19 at 14:15
67

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
Artur Barseghyan
  • 12,746
  • 4
  • 52
  • 44
  • 2
    As mentioned in the other answer, it is possible that the error is not caught. Therefore I think this should be the accepted answer. – Jorrick Sleijster Aug 20 '17 at 17:15
  • `AttributeError: module 'pip' has no attribute 'get_installed_distributions'` – Nico Schlömer Jun 15 '18 at 09:41
  • Probably it was take out from most recent version of pip. Which version are you using? I think in 8.x it still worked. – Artur Barseghyan Jun 15 '18 at 09:42
  • 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." – Nico Schlömer Jun 15 '18 at 09:44
  • This works indeed (for now). It should be noted however that pip itself uses against doing this. – Nico Schlömer Jun 15 '18 at 09:56
  • 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? – Artur Barseghyan Jun 15 '18 at 09:58
  • 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. – Artur Barseghyan Jun 15 '18 at 10:02
  • @NicoSchlömer: Fair enough, see my new updated answer. :) – Artur Barseghyan Jun 15 '18 at 10:22
  • 1
    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. – mountrix Aug 06 '18 at 14:50
  • @mountrix: Why would you check for availability of `json`? It's a part of a standard library. Therefore, irrelevant. – Artur Barseghyan Aug 06 '18 at 15:30
  • @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? – mountrix Aug 06 '18 at 17:47
  • @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 http://python-stdlib-list.readthedocs.io/ – Artur Barseghyan Aug 06 '18 at 19:02
  • This assumes that your runtime has pip installed. That is not a safe assumption. – Christopher Aug 08 '18 at 19:47
  • @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`. – Artur Barseghyan Aug 08 '18 at 20:11
  • 1
    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', ...]` – Buju Sep 16 '19 at 16:04
  • @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. – Artur Barseghyan Sep 16 '19 at 20:07
  • 1
    @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. – Buju Sep 18 '19 at 13:04
  • @Buju: That's really strange. I'll update the answer and add MacOS section. Thank you! – Artur Barseghyan Sep 18 '19 at 13:23
  • 2
    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 @ice.nicer about `find_spec()` is right. – Arthur Sep 25 '19 at 20:24
  • @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`. – Artur Barseghyan Sep 26 '19 at 19:35
42

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
Ognjen Vukovic
  • 441
  • 4
  • 4
10

Open your command prompt type

pip3 list
Akhil G
  • 107
  • 1
  • 4
7

In the Terminal type

pip show some_package_name

Example

pip show matplotlib
Andrew
  • 36,676
  • 11
  • 141
  • 113
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: 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
Herpes Free Engineer
  • 2,425
  • 2
  • 27
  • 34
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.

Lyudmil Nenov
  • 247
  • 2
  • 6
  • Yes, the package vs. module distinction can be quite important. For example both [python-magic](https://github.com/ahupp/python-magic) and [file-magic](https://github.com/file/file/tree/master/python) provide modules named `magic` but their interfaces are incompatible with each other. Also in 3.8 [importlib.metadata](https://docs.python.org/3/library/importlib.metadata.html) was added and imho it's rather handy. – ish-west Oct 17 '22 at 18:04
4
if pip list | grep -q \^'PACKAGENAME\s'
  # installed ...
else
  # not installed ...
fi
Sapphire_Brick
  • 1,560
  • 12
  • 26
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
...
...
Udesh
  • 2,415
  • 2
  • 22
  • 32
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")
Yousha Aleayoub
  • 4,532
  • 4
  • 53
  • 64
sh_mirzaee
  • 41
  • 2
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.

Gergely M
  • 583
  • 4
  • 11
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

lucab91
  • 11
  • 2
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))
Alexander Zhak
  • 9,140
  • 4
  • 46
  • 72
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
$
Deepu Sahni
  • 479
  • 5
  • 9
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).

Kim
  • 592
  • 3
  • 13
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

Rdimo
  • 378
  • 2
  • 14
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.

Prahlad Yeri
  • 3,567
  • 4
  • 25
  • 55
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
}
gebbissimo
  • 2,137
  • 2
  • 25
  • 35
-1

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

eduffy
  • 39,140
  • 13
  • 95
  • 92
-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?

Melih
  • 13
  • 1
  • 5
  • 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. – Heather Sawatsky Apr 07 '21 at 14:08