1261

How do I get a list of Python modules installed on my computer?

7
  • 93
    you can just do >>>help() and then >>>modules
    – julz12
    Commented May 28, 2014 at 17:30
  • 3
    Is there an alternative? help() hangs for me. Commented Feb 26, 2018 at 13:00
  • 3
    A lot of these answers assume you have access to a command line. If you are using AWS Lambda, you have to do it all from inside Python. See stackoverflow.com/a/54939905/117471 Commented Mar 1, 2019 at 7:40
  • 17
    What is wrong with pip list?
    – H Aßdøµ
    Commented Aug 3, 2020 at 0:40
  • 1
    Adding this oneliner from Julius Naeumann comment: python3 -c "help('modules')"
    – sodimel
    Commented Jan 8, 2021 at 10:15

34 Answers 34

1277
help('modules')

in a Python shell/prompt.

16
  • 13
    @dF pydoc modules works. You should submit it as an answer.
    – Abizern
    Commented Apr 11, 2009 at 13:30
  • 3
    nobar, zanbri, @Joe Frambach: on Ubuntu? There's a bug described here: bugs.launchpad.net/ubuntu/+source/python2.7/+bug/896836 Commented Apr 11, 2013 at 17:30
  • 3
    how can i get extra info about where the modules are installed and what is the current version?
    – curious
    Commented Nov 7, 2014 at 9:48
  • 25
    python -c 'help("modules")'
    – kenorb
    Commented Nov 18, 2019 at 16:56
  • 1
    for python 2.7+ or maybe for python 3.7+ as well (use double quotes outside): python -c "help('modules')" Commented Mar 15, 2022 at 14:13
665
+100

Solution

Do not use with pip > 10.0!

My 50 cents for getting a pip freeze-like list from a Python script:

import pip
installed_packages = pip.get_installed_distributions()
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
     for i in installed_packages])
print(installed_packages_list)

As a (too long) one liner:

sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])

Giving:

['behave==1.2.4', 'enum34==1.0', 'flask==0.10.1', 'itsdangerous==0.24',
 'jinja2==2.7.2', 'jsonschema==2.3.0', 'markupsafe==0.23', 'nose==1.3.3',
 'parse-type==0.3.4', 'parse==1.6.4', 'prettytable==0.7.2', 'requests==2.3.0',
 'six==1.6.1', 'vioozer-metadata==0.1', 'vioozer-users-server==0.1',
 'werkzeug==0.9.4']

Scope

This solution applies to the system scope or to a virtual environment scope, and covers packages installed by setuptools, pip and (god forbid) easy_install.

My use case

I added the result of this call to my Flask server, so when I call it with http://example.com/exampleServer/environment I get the list of packages installed on the server's virtualenv. It makes debugging a whole lot easier.

Caveats

I have noticed a strange behaviour of this technique - when the Python interpreter is invoked in the same directory as a setup.py file, it does not list the package installed by setup.py.

Steps to reproduce:

Create a virtual environment

$ cd /tmp
$ virtualenv test_env
New python executable in test_env/bin/python
Installing setuptools, pip...done.
$ source test_env/bin/activate
(test_env) $

Clone a Git repository with setup.py

(test_env) $ git clone https://github.com/behave/behave.git
Cloning into 'behave'...
remote: Reusing existing pack: 4350, done.
remote: Total 4350 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4350/4350), 1.85 MiB | 418.00 KiB/s, done.
Resolving deltas: 100% (2388/2388), done.
Checking connectivity... done.

We have behave's setup.py in /tmp/behave:

(test_env) $ ls /tmp/behave/setup.py
    /tmp/behave/setup.py

Install the Python package from the Git repository

(test_env) $ cd /tmp/behave && pip install .
running install
...
Installed /private/tmp/test_env/lib/python2.7/site-packages/enum34-1.0-py2.7.egg
Finished processing dependencies for behave==1.2.5a1

If we run the aforementioned solution from /tmp

>>> import pip
>>> sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
['behave==1.2.5a1', 'enum34==1.0', 'parse-type==0.3.4', 'parse==1.6.4', 'six==1.6.1']
>>> import os
>>> os.getcwd()
'/private/tmp'

If we run the aforementioned solution from /tmp/behave

>>> import pip
>>> sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
['enum34==1.0', 'parse-type==0.3.4', 'parse==1.6.4', 'six==1.6.1']
>>> import os
>>> os.getcwd()
'/private/tmp/behave'

behave==1.2.5a1 is missing from the second example, because the working directory contains behave's setup.py file.

I could not find any reference to this issue in the documentation. Perhaps I shall open a bug for it.

26
  • 5
    Thank you for this answer! I think it better answers the question because I ask "locally" installed Python modules. Pip freeze is also not always the way to go. This works better - I think. Commented May 27, 2014 at 10:54
  • 3
    @Masi Just added a detailed explanation of the caveat of this solution. It is indeed a strange one.
    – Adam Matan
    Commented Jun 4, 2014 at 6:41
  • 39
    An alternative: import pkg_resources; installed_packages = [(d.project_name, d.version) for d in pkg_resources.working_set]
    – ebolyen
    Commented Sep 14, 2016 at 17:45
  • 17
    As of pip 10, this answer will no longer work. The comment from @ebolyen shows alternative commands that do work. I came to the same conclusion and posted the complete revised code below.
    – Big_Al_Tx
    Commented Apr 25, 2018 at 3:06
  • 12
    In recent versions of pip, this won't work, yielding an error message saying AttributeError: module 'pip' has no attribute 'get_installed_distributions'. Commented Dec 28, 2018 at 15:12
355

Now, these methods I tried myself, and I got exactly what was advertised: All the modules.

Alas, really you don't care much about the stdlib. You know what you get with a Python install.

Really, I want the stuff that I installed.

What actually, surprisingly, worked just fine was:

pip freeze

Which returned:

Fabric==0.9.3
apache-libcloud==0.4.0
bzr==2.3b4
distribute==0.6.14
docutils==0.7
greenlet==0.3.1
ipython==0.10.1
iterpipes==0.4
libxml2-python==2.6.21

I say "surprisingly", because the package install tool is the exact place one would expect to find this functionality, although not under the name 'freeze', but Python packaging is so weird that I am flabbergasted that this tool makes sense. Pip 0.8.2 and Python 2.7.

9
  • 4
    I guess the idea behind the name is that you get a "frozen" snapshot of what is installed right now, which you can later feed back into pip to get exactly the same modules installed in a different environment. Commented Dec 16, 2011 at 1:25
  • Arash, you can install pip in Windows too! First install setuptools and then use easy_install to install pip :)
    – gawbul
    Commented May 8, 2012 at 10:02
  • This is excellent, but it seems to miss some of the libraries I installed. For example, it doesn't list PyQt.
    – Junuxx
    Commented Jun 2, 2012 at 10:27
  • 11
    Starting from pip 1.3 there's the list command. Commented Mar 13, 2013 at 22:00
  • it works. What a mess python is. Why can they not get their act together and come up with solutions similar to what exists in Rails? (Gemfile, bundler, rvm)
    – Dimitris
    Commented Jul 23, 2013 at 11:38
161

Since pip version 1.3, you've got access to:

pip list

Which seems to be syntactic sugar for "pip freeze". It will list all of the modules particular to your installation or virtualenv, along with their version numbers. Unfortunately, it does not display the current version number of any module, nor does it wash your dishes or shine your shoes.

4
  • 9
    There is also pip list --local for distinguishing between virtualenv and global site packages, discussed here.
    – 0 _
    Commented Jul 9, 2014 at 18:28
  • 3
    By far the best. It also retrieves the versions.
    – aerijman
    Commented Apr 26, 2019 at 1:17
  • 1
    pip list is the simplest and the best. Here are the options and details. Commented Jan 15, 2020 at 3:01
  • 2
    pip list returns distributions, not modules. Distributions and modules have the same name enough to make it seem like this returns modules. See my answer
    – Mandera
    Commented Oct 5, 2022 at 9:13
95
  • In ipython you can type "importTab".

  • In the standard Python interpreter, you can type "help('modules')".

  • At the command-line, you can use pydoc modules.

  • In a script, call pkgutil.iter_modules().

3
  • 7
    pkgutil.iter_modules() works, the pip solution above doesn't list all packages, just the ones installed via pip. Commented May 29, 2014 at 20:07
  • 2
    Awesome! I think they have improved documentation, since the question was asked. pydoc modules spam searches spam in docs of modules. The last point seems to give you the sufficient information to use the module. @metaperture Can you, please, give an example how you list all local modules installed (not the massive list of stlib by help('modules')) by pkgutil.iter_modules(). Commented May 29, 2014 at 21:17
  • 3
    @LéoLéopoldHertz준영 Try this snippet: python -c 'import pkgutil;print [x[1] for x in list(pkgutil.iter_modules())]'. It should dump all the module names as one really big Python list. The x[1] bit is used to pluck the module name out of the tuples generated by pkgutil.iter_modules(). Commented Feb 9, 2017 at 8:08
94

I just use this to see currently used modules:

import sys as s
s.modules.keys()

which shows all modules running on your python.

For all built-in modules use:

s.modules

Which is a dict containing all modules and import objects.

6
  • 2
    # After you import sys "import sys as s" you can print with: print sys.modules.keys()
    – Dan Evans
    Commented Jun 22, 2012 at 23:44
  • Not sure why my post was edited, but thank you for using the info I posted to correct the mistakes in prior posts. You will return errors if you use help() vs help(''). This goes for dir('') & sys('') etc. as well. Hope this helps & is not removed.
    – Dan Evans
    Commented Jun 24, 2012 at 21:03
  • Ignore my last post, this post was not edited. I was thinking of a similar post found here: stackoverflow.com/questions/139180/… Sorry for the confusion.
    – Dan Evans
    Commented Jun 24, 2012 at 22:56
  • 9
    Upvoted, because this is the only method that seems to work on constrained systems which have neither pydoc nor pip installed (a NAS in my case).
    – Thomas
    Commented Oct 23, 2016 at 10:09
  • 1
    Agreed with Thomas. I'm using repl.it , for example, which is also a constrained type of environment. help('modules') just hangs without response for me. But this approach with sys works perfectly Commented Jan 20, 2017 at 19:47
67

In a normal shell, just use

pydoc modules
5
  • It appears that the above works only on 'nix platforms. In any case, I found and ran the script, adapting the command as follows: c:\bin\pythos_2.7\lib\pydoc.py modules - that list took forever to build, the format sucks, and it omits the installed version number. I'll pass. Commented Jul 28, 2017 at 5:38
  • 4
    @DavidA.Gray Just tried this on a Windows machine with Python 3, and it does in fact work. Using the python windows launcher you can do py -m pydoc modules in cmd or Powershell.
    – VKK
    Commented Mar 17, 2018 at 19:12
  • pydoc modules didn't work for me in Windows 10 with Python 3.6, but @VKK modification: py -m pydoc modules does work in cmd/Powershell.
    – Martin
    Commented Apr 18, 2019 at 18:54
  • What is "a normal shell"? Commented Sep 30, 2023 at 21:17
  • OK, the OP has left the building: Last seen more than 2 years ago Commented Sep 30, 2023 at 21:18
64

As of pip 10, the accepted answer will no longer work. The development team has removed access to the get_installed_distributions routine. There is an alternate function in the setuptools for doing the same thing. Here is an alternate version that works with pip 10:

import pkg_resources
installed_packages = pkg_resources.working_set
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
     for i in installed_packages])
print(installed_packages_list)

Please let me know if it will or won't work in previous versions of pip, too.

14
  • 2
    I have been searching for this solution and wracking my brain trying to figure out pkg_resources. If I could upvote this more than once I would. Thank you, @Big_Al_Tx ! Update: Except.... when I do a 'pip freeze' in my virtual environment and compare it to the output of this, there are packages that are missing. Any thoughts on why that could/would happen?
    – numberwhun
    Commented Jul 4, 2018 at 19:40
  • @numberwhun - I'm glad this worked for you. I'm sorry, but I don't have an answer for the discrepancy with pip freeze; the depth of my knowledge on this topic is rather limited. I sort-of fumbled my way to the solution when the accepted answer didn't work for me and I tried combining it with an answer related to setuptools and got it to work.
    – Big_Al_Tx
    Commented Jul 5, 2018 at 20:59
  • github.com/pypa/pip/issues/5243 - The talk of development team about removed access to the get_installed_distributions routine.
    – bl79
    Commented Jul 26, 2018 at 16:52
  • @bl79 - I think that's the exact place where I got the reference for setuptools.
    – Big_Al_Tx
    Commented Jul 27, 2018 at 17:55
  • @Big_Al_Tx: Well, I sort of worked around the setuptools option (which was waaaay to obfuscated for my needs) and I went with this: installed_pkgs = subprocess.check_output(['pip', 'freeze']) It does exactly what I needed it to do.... Yay!!
    – numberwhun
    Commented Aug 15, 2018 at 23:12
42

Works Regardless of Pip Version

Run the following in your python editor or IPython:

import pkg_resources
installed_packages = {d.project_name: d.version for d in pkg_resources.working_set}
print(installed_packages)

Read other answers and pulled together this combo, which is quickest and easiest inside Python.

Find the specific Packages

Conveniently you can then get items from your dict easily, i.e.

installed_packages['pandas'] >> '1.16.4'

Using Pip List Well

!pip list will run inside your jupyter notebook if working there, simplifying the 'quick check' Combine with other utilities like grep(if you have installed) pip list | grep pandas will get you your current pandas version for example

4
  • pkg_resources is part of setuptools. It has not much to do with pip.
    – sinoroc
    Commented Jun 10, 2020 at 14:46
  • Yep @sinoroc, but the accepted answer doesn't work beyond pip 10 which was the intent of the title Commented Jun 10, 2020 at 15:02
  • 1
    Then I don't understand the logic of your title, since your solution is not limited to recent versions of pip. It should work for any version of pip since it doesn't use pip at all. Also you might want to look at importlib.metadata from Python's standard library since 3.8: docs.python.org/3/library/importlib.metadata.html
    – sinoroc
    Commented Jun 10, 2020 at 15:53
  • working_set returns distributions, not modules. Distributions and modules have the same name enough to make it seem like this returns modules. See my answer
    – Mandera
    Commented Oct 5, 2022 at 9:14
39

If we need to list the installed packages in the Python shell, we can use the help command as follows

>>> help('modules package')
1
  • Only returns modules which has the word package in it's name or in it's docstring, which a lot of modules does not have.
    – Mandera
    Commented Jan 15, 2021 at 9:04
26

I normally use pip list to get a list of packages (with version).

This works in a virtual environment too, of course. To show what's installed in only the virtual environment (not global packages), use pip list --local.

Here's documentation showing all the available pip list options, with several good examples.

23

$ pip freeze -- Output installed packages in requirements format
$ pip list -- List installed packages.

0
20

This will help

In a terminal or IPython, type:

help('modules')

then

In [1]: import                      #import press-TAB
Display all 631 possibilities? (y or n)
ANSI                   audiodev               markupbase
AptUrl                 audioop                markupsafe
ArgImagePlugin         avahi                  marshal
BaseHTTPServer         axi                    math
Bastion                base64                 md5
BdfFontFile            bdb                    mhlib
BmpImagePlugin         binascii               mimetools
BufrStubImagePlugin    binhex                 mimetypes
CDDB                   bisect                 mimify
CDROM                  bonobo                 mmap
CGIHTTPServer          brlapi                 mmkeys
Canvas                 bsddb                  modulefinder
CommandNotFound        butterfly              multifile
ConfigParser           bz2                    multiprocessing
ContainerIO            cPickle                musicbrainz2
Cookie                 cProfile               mutagen
Crypto                 cStringIO              mutex
CurImagePlugin         cairo                  mx
DLFCN                  calendar               netrc
DcxImagePlugin         cdrom                  new
Dialog                 cgi                    nis
DiscID                 cgitb                  nntplib
DistUpgrade            checkbox               ntpath
0
14

This solution is primary based on modules importlib and pkgutil and work with CPython 3.4 and CPython 3.5, but has no support for the CPython 2.


Explanation

  1. sys.builtin_module_names - names all built-in modules (look my answer here)
  2. pkgutil.iter_modules() - returns an information about all available modules
  3. importlib.util.find_spec() - returns an information about importing module, if exists
  4. BuiltinImporter - an importer for built-in modules (docs)
  5. SourceFileLoader - an importer for a standard Python module (by default has extension *.py) (docs)
  6. ExtensionFileLoader - an importer for modules as shared library (written on the C or C++)

Full code

import sys
import os
import shutil
import pkgutil
import importlib
import collections

if sys.version_info.major == 2:
    raise NotImplementedError('CPython 2 is not supported yet')


def main():

    # Name this file (module)
    this_module_name = os.path.basename(__file__).rsplit('.')[0]

    # Dict for loaders with their modules
    loaders = collections.OrderedDict()

    # Names's of build-in modules
    for module_name in sys.builtin_module_names:

        # Find an information about a module by name
        module = importlib.util.find_spec(module_name)

        # Add a key about a loader in the dict, if not exists yet
        if module.loader not in loaders:
            loaders[module.loader] = []

        # Add a name and a location about imported module in the dict
        loaders[module.loader].append((module.name, module.origin))

    # All available non-build-in modules
    for module_name in pkgutil.iter_modules():

        # Ignore this module
        if this_module_name == module_name[1]:
            continue

        # Find an information about a module by name
        module = importlib.util.find_spec(module_name[1])

        # Add a key about a loader in the dict, if not exists yet
        loader = type(module.loader)
        if loader not in loaders:
            loaders[loader] = []

        # Add a name and a location about imported module in the dict
        loaders[loader].append((module.name, module.origin))

    # Pretty print
    line = '-' * shutil.get_terminal_size().columns
    for loader, modules in loaders.items():
        print('{0}\n{1}: {2}\n{0}'.format(line, len(modules), loader))
        for module in modules:
            print('{0:30} | {1}'.format(module[0], module[1]))


if __name__ == '__main__':
    main()

Usage

For the CPython 3.5 (truncated)

python3.5 python_modules_info.py

Output:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
30: <class '_frozen_importlib.BuiltinImporter'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_ast                           | built-in
_codecs                        | built-in
_collections                   | built-in
_functools                     | built-in
_imp                           | None
_io                            | built-in
_locale                        | built-in
_operator                      | built-in
_signal                        | built-in
_sre                           | built-in
_stat                          | built-in
_string                        | built-in
_symtable                      | built-in
_thread                        | built-in
(****************************truncated*******************************)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
227: <class '_frozen_importlib_external.SourceFileLoader'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
__future__                     | /usr/local/lib/python3.5/__future__.py
_bootlocale                    | /usr/local/lib/python3.5/_bootlocale.py
_collections_abc               | /usr/local/lib/python3.5/_collections_abc.py
_compat_pickle                 | /usr/local/lib/python3.5/_compat_pickle.py
_compression                   | /usr/local/lib/python3.5/_compression.py
_dummy_thread                  | /usr/local/lib/python3.5/_dummy_thread.py
_markupbase                    | /usr/local/lib/python3.5/_markupbase.py
_osx_support                   | /usr/local/lib/python3.5/_osx_support.py
_pydecimal                     | /usr/local/lib/python3.5/_pydecimal.py
_pyio                          | /usr/local/lib/python3.5/_pyio.py
_sitebuiltins                  | /usr/local/lib/python3.5/_sitebuiltins.py
(****************************truncated*******************************)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
64: <class '_frozen_importlib_external.ExtensionFileLoader'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_bisect                        | /usr/local/lib/python3.5/lib-dynload/_bisect.cpython-35m-x86_64-linux-gnu.so
_bz2                           | /usr/local/lib/python3.5/lib-dynload/_bz2.cpython-35m-x86_64-linux-gnu.so
_codecs_cn                     | /usr/local/lib/python3.5/lib-dynload/_codecs_cn.cpython-35m-x86_64-linux-gnu.so
_codecs_hk                     | /usr/local/lib/python3.5/lib-dynload/_codecs_hk.cpython-35m-x86_64-linux-gnu.so
_codecs_iso2022                | /usr/local/lib/python3.5/lib-dynload/_codecs_iso2022.cpython-35m-x86_64-linux-gnu.so
(****************************truncated*******************************)

For the CPython 3.4 (truncated)

python3.4 python_modules_info.py

Output:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
54: <class '_frozen_importlib.BuiltinImporter'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_ast                           | built-in
_bisect                        | built-in
_codecs                        | built-in
_collections                   | built-in
_datetime                      | built-in
_elementtree                   | built-in
_functools                     | built-in
_heapq                         | built-in
_imp                           | None
_io                            | built-in
_locale                        | built-in
_md5                           | built-in
_operator                      | built-in
_pickle                        | built-in
_posixsubprocess               | built-in
_random                        | built-in
(****************************truncated*******************************)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
246: <class '_frozen_importlib.SourceFileLoader'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
__future__                     | /usr/lib/python3.4/__future__.py
_bootlocale                    | /usr/lib/python3.4/_bootlocale.py
_collections_abc               | /usr/lib/python3.4/_collections_abc.py
_compat_pickle                 | /usr/lib/python3.4/_compat_pickle.py
_dummy_thread                  | /usr/lib/python3.4/_dummy_thread.py
_markupbase                    | /usr/lib/python3.4/_markupbase.py
_osx_support                   | /usr/lib/python3.4/_osx_support.py
_pyio                          | /usr/lib/python3.4/_pyio.py
(****************************truncated*******************************)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
44: <class '_frozen_importlib.ExtensionFileLoader'>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_bz2                           | /usr/lib/python3.4/lib-dynload/_bz2.cpython-34m-x86_64-linux-gnu.so
_codecs_cn                     | /usr/lib/python3.4/lib-dynload/_codecs_cn.cpython-34m-x86_64-linux-gnu.so
_codecs_hk                     | /usr/lib/python3.4/lib-dynload/_codecs_hk.cpython-34m-x86_64-linux-gnu.so
_codecs_iso2022                | /usr/lib/python3.4/lib-dynload/_codecs_iso2022.cpython-34m-x86_64-linux-gnu.so
_codecs_jp                     | /usr/lib/python3.4/lib-dynload/_codecs_jp.cpython-34m-x86_64-linux-gnu.so
_codecs_kr                     | /usr/lib/python3.4/lib-dynload/_codecs_kr.cpython-34m-x86_64-linux-gnu.so
_codecs_tw                     | /usr/lib/python3.4/lib-dynload/_codecs_tw.cpython-34m-x86_64-linux-gnu.so
_crypt                         | /usr/lib/python3.4/lib-dynload/_crypt.cpython-34m-x86_64-linux-gnu.so
(****************************truncated*******************************)
6
  • Can you please compare your approach to Adam's approach here stackoverflow.com/a/23885252/54964 Commented Mar 8, 2017 at 16:03
  • @Léo Léopold Hertz, why are you need it? Commented Mar 8, 2017 at 16:39
  • To understand how your approach is better/worser than Adam's approach. Commented Mar 8, 2017 at 20:40
  • 1
    @Léo Léopold Hertz. A short answer: try it yourself in a production and draw conclusions yourself. Long answer: the Adam's approach is based on the pip - package management system used to install and manage software packages written in Python and a result pip.get_installed_distributions() returns modules installed with the pip. My answer entirely based on the Python`s standard library and cover all modules available for import. A biggest drawback my answer - no a support for the the CPython 2. Commented Mar 9, 2017 at 13:16
  • 1
    @Léo Léopold Hertz you are mistaken, it does it. I tested it on my computer. My answer contains special meaning **truncated**, where a output is truncated. Maybe you not careful, but if it does not it, so to send me an information about your system and the Python implementation, I will make addition research for fix it. Commented Mar 9, 2017 at 13:29
13

Very simple searching using pkgutil.iter_modules

from pkgutil import iter_modules
a=iter_modules()
while True:
    try: x=a.next()
    except: break
    if 'searchstr' in x[1]: print x[1]
2
  • 2
    is there any reason to use while instead of a for loop? I wrote using for m in iter_modules() and it did work as well.
    – Joao Ponte
    Commented May 11, 2020 at 14:12
  • [m.name for m in iter_modules() if '_' not in m.name and not any([ex in m.name for ex in ['easy_install', 'pip', 'wheel', 'setuptool', 'pkg_resources'] ])] First it removes the underscore named modules, then it removes items in the exception list. :D Commented Sep 19, 2022 at 10:48
13

On Windows, enter this in cmd:

cd C:\python\libs
python -m pip freeze
2
  • This worked for me using: python3 -m pip freeze - for python 3.5.3.
    – dpminusa
    Commented Dec 18, 2017 at 14:10
  • This works well and you do not need to be in the libs directory as well if your variables are defined
    – mcy
    Commented Apr 11, 2018 at 9:05
12

I ran into a custom installed python 2.7 on OS X. It required X11 to list modules installed (both using help and pydoc).

To be able to list all modules without installing X11 I ran pydoc as http-server, i.e.:

pydoc -p 12345

Then it's possible to direct Safari to http://localhost:12345/ to see all modules.

0
12

I'm comparing five methods to retrieve installed "modules", all of which I've seen in this thread

iter_modules help("modules") builtin_module_names pip list working_set
Includes distributions ✔️ ✔️
Includes modules (No built-in) ✔️ ✔️
Includes built-in modules ✔️ ✔️
Includes frozen ✔️ ✔️
Includes venv ✔️ ✔️ ✔️ ✔️
Includes global ✔️ ✔️ ✔️ ✔️
Includes editable installs ✔️ ✔️ ✔️ ✔️
Includes PyCharm helpers ✔️
Lowers capital letters ✔️
Time taken (665 modules total) 53.7 msec 1.03 sec 577 nsec 284 msec 36.2 usec

Summary

  • pip list and working_set are for distributions, not modules.
  • iter_modules and help("modules") are very similar, the biggest difference is that iter_modules doesn't include built-in.
  • pip list and working_set are very similar, only difference is that working_set lowers all capital letters.
  • Built-in modules are only included by help("modules") and builtin_module_names.

Related caveats

  • Distributions, packages, and modules often have identical names making it easy to mistake one for the other.
  • importlib.util.find_spec is for modules and is case-sensitive.
  • sys.modules only lists imported modules.

Distributions

I'm saying distribution instead of package because I think it will reduce misunderstandings. A distribution/package can have multiple packages/modules inside it.

An installed distribution is not always importable by the same name. For example pip install Pillow is imported with import PIL. Sometimes a distribution even makes multiple modules importable.

Methods (Each column in order)

iter_modules

import pkgutil
{module.name for module in pkgutil.iter_modules()}

help("modules") (Only prints in terminal)

help("modules")

builtin_module_names

import sys
set(sys.builtin_module_names)

pip list (Only prints in terminal)

pip list in terminal

working_set

import pkg_resources
{pkg.key for pkg in pkg_resources.working_set}

Conclusion

import sys
import pkgutil

def get_installed_modules_names():
    iter_modules = {module.name for module in pkgutil.iter_modules()}
    builtin = sys.builtin_module_names
    return set.union(iter_modules, builtin)
1
10

Warning: Adam Matan discourages this use in pip > 10.0. Also, read @sinoroc's comment below

This was inspired by Adam Matan's answer (the accepted one):

import tabulate
try:
  from pip import get_installed_distributions
except:
  from pip._internal.utils.misc import get_installed_distributions

tabpackages = []
for _, package in sorted([('%s %s' % (i.location, i.key), i) for i in get_installed_distributions()]):
  tabpackages.append([package.location, package.key, package.version])

print(tabulate.tabulate(tabpackages))

which then prints out a table in the form of

cd ~/python
python installed_packages.py

Output:

-------------------------------------------  --------------  ------
/home/pi/.local/lib/python2.7/site-packages  enum-compat     0.0.2
/home/pi/.local/lib/python2.7/site-packages  enum34          1.1.6
/home/pi/.local/lib/python2.7/site-packages  pexpect         4.2.1
/home/pi/.local/lib/python2.7/site-packages  ptyprocess      0.5.2
/home/pi/.local/lib/python2.7/site-packages  pygatt          3.2.0
/home/pi/.local/lib/python2.7/site-packages  pyserial        3.4
/usr/local/lib/python2.7/dist-packages       bluepy          1.1.1
/usr/local/lib/python2.7/dist-packages       click           6.7
/usr/local/lib/python2.7/dist-packages       click-datetime  0.2
/usr/local/lib/python2.7/dist-packages       construct       2.8.21
/usr/local/lib/python2.7/dist-packages       pyaudio         0.2.11
/usr/local/lib/python2.7/dist-packages       tabulate        0.8.2
-------------------------------------------  --------------  ------

which lets you then easily discern which packages you installed with and without sudo.


A note aside: I've noticed that when I install a packet once via sudo and once without, one takes precedence so that the other one isn't being listed (only one location is shown). I believe that only the one in the local directory is then listed. This could be improved.

4
  • 2
    No. This is not recommended, see here: pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program
    – sinoroc
    Commented Dec 12, 2019 at 14:20
  • 2
    @sinoroc Thank you for pointing this out. Points 1 to 3 don't seem to be applicable to this solution, as this script has the sole purpose of using pip once and then exiting. It appears to be more of a problem that the behavior could change.
    – Daniel F
    Commented Dec 12, 2019 at 15:51
  • 1
    Agreed, the reasons why there is no public API do not apply to this particular piece of code. But since pip is not bound to guarantee a public API it is free to change its internal APIs, code structure, etc. in a later release, like it already did before. This is why this code has a try/except, to catch the previous internal code reorganization that was meant to clarify that internal APIs are internal APIs not public ones (_internal). All in all, it obviously works but is bad practice. There are better alternatives, some are in the other answers to this question.
    – sinoroc
    Commented Dec 12, 2019 at 16:12
  • 1
    this script wont work if the "pip" module is not there. Commented Jan 24, 2020 at 16:59
9

In case you have an Anaconda Python distribution installed, you could also use

conda list

in addition to the solutions described in previous answers.

3
  • Where/how do you run this line? Commented Aug 14, 2014 at 16:34
  • If you are on your UNIX/Mac OS X machine, open up your terminal and just type conda install, it should work :)
    – Shreyas
    Commented Aug 14, 2014 at 19:27
  • I'm on a Windows 7 machine. I found it in my path actually, but conda.exe is in AppData\Local\Continuum\Anaconda\Scripts. Commented Aug 14, 2014 at 19:47
8

Aside from using pip freeze I have been installing yolk in my virtual environments.

6
  1. to get all available modules, run sys.modules
  2. to get all installed modules (read: installed by pip), you may look at pip.get_installed_distributions()

For the second purpose, example code:

import pip
for package in pip.get_installed_distributions():
    name = package.project_name # SQLAlchemy, Django, Flask-OAuthlib
    key = package.key # sqlalchemy, django, flask-oauthlib
    module_name = package._get_metadata("top_level.txt") # sqlalchemy, django, flask_oauthlib
    location = package.location # virtualenv lib directory etc.
    version = package.version # version number
8
  • The command sys.modules does not work in the newest OSX's Python. NameError: name 'system' is not defined. Commented Jan 21, 2014 at 9:17
  • @Masi Did you mean /usr/bin/python or the one come from python.org ? For the former one, I can use sys.modules without a problem.
    – yegle
    Commented Jan 21, 2014 at 15:38
  • I mean /usr/bin/python. Commented Jan 21, 2014 at 19:21
  • @Masi Not sure if you are still interested in this problem. Apparently you are using system.modules instead of sys.modules.
    – yegle
    Commented Sep 3, 2014 at 17:51
  • Lol. My mistake was that I did not originally import sys -package. So running instead import sys; sys.modules work as expected. Commented Sep 3, 2014 at 18:10
5

pip freeze does it all, finding packages. However, one can simply write the following command to list all paths where Python packages are.

>>> import site; site.getsitepackages()
['/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']
4

There are many way to skin a cat.

  • The most simple way is to use the pydoc function directly from the shell with:
    pydoc modules

  • But for more information use the tool called pip-date that also tell you the installation dates.
    pip install pip-date


enter image description here

1
4

I needed to find the specific version of packages available by default in AWS Lambda. I did so with a mashup of ideas from this page. I'm sharing it for posterity.

import pkgutil

__version__ = '0.1.1'

def get_ver(name):
    try:
        return str(__import__(name).__version__)
    except:
        return None

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': [{
                   'path': m.module_finder.path,
                   'name': m.name,
                   'version': get_ver(m.name),
                 } for m in list(pkgutil.iter_modules())
                 #if m.module_finder.path == "/var/runtime" # Uncomment this if you only care about a certain path
                ],
    }

What I discovered is that the provided boto3 library was way out of date and it wasn't my fault that my code was failing. I just needed to add boto3 and botocore to my project. But without this I would have been banging my head thinking my code was bad.

{
  "statusCode": 200,
  "body": [
    {
      "path": "/var/task",
      "name": "lambda_function",
      "version": "0.1.1"
    },
    {
      "path": "/var/runtime",
      "name": "bootstrap",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "boto3",
      "version": "1.9.42"
    },
    {
      "path": "/var/runtime",
      "name": "botocore",
      "version": "1.12.42"
    },
    {
      "path": "/var/runtime",
      "name": "dateutil",
      "version": "2.7.5"
    },
    {
      "path": "/var/runtime",
      "name": "docutils",
      "version": "0.14"
    },
    {
      "path": "/var/runtime",
      "name": "jmespath",
      "version": "0.9.3"
    },
    {
      "path": "/var/runtime",
      "name": "lambda_runtime_client",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "lambda_runtime_exception",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "lambda_runtime_marshaller",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "s3transfer",
      "version": "0.1.13"
    },
    {
      "path": "/var/runtime",
      "name": "six",
      "version": "1.11.0"
    },
    {
      "path": "/var/runtime",
      "name": "test_bootstrap",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "test_lambda_runtime_client",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "test_lambda_runtime_marshaller",
      "version": null
    },
    {
      "path": "/var/runtime",
      "name": "urllib3",
      "version": "1.24.1"
    },
    {
      "path": "/var/lang/lib/python3.7",
      "name": "__future__",
      "version": null
    },
...

What I discovered was also different from what they officially publish. At the time of writing this:

  • Operating system – Amazon Linux
  • AMI – amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2
  • Linux kernel – 4.14.77-70.59.amzn1.x86_64
  • AWS SDK for JavaScript – 2.290.0\
  • SDK for Python (Boto 3) – 3-1.7.74 botocore-1.10.74
0
3

There are many ideas, initially I am pondering on these two:

pip

cons: not always installed

help('modules')

cons: output to console; with broken modules (see ubuntu...) can segfault

I need an easy approach, using basic libraries and compatible with old python 2.x

And I see the light: listmodules.py

Hidden in the documentation source directory in 2.5 is a small script that lists all available modules for a Python installation.

Pros:

uses only imp, sys, os, re, time

designed to run on Python 1.5.2 and newer

the source code is really compact, so you can easy tinkering with it, for example to pass an exception list of buggy modules (don't try to import them)

3
pip install pip-chill 
pip-chill
2

Here is a Python code solution that will return a list of modules installed. One can easily modify the code to include version numbers.

import subprocess
import sys
from pprint import pprint

installed_packages = reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']).decode('utf-8')
installed_packages = installed_packages.split('\r\n')
installed_packages = [pkg.split('==')[0] for pkg in installed_packages if pkg != '']
pprint(installed_packages)
1

Installation

pip install pkgutil

Code

import pkgutil

for i in pkgutil.iter_modules(None): # returns a tuple (path, package_name, ispkg_flag)
    print(i[1]) #or you can append it to a list

Sample Output:

multiprocessing
netrc
nntplib
ntpath
nturl2path
numbers
opcode
pickle
pickletools
pipes
pkgutil
1

Attention

Use of pkg_resources is deprecated in favor of importlib.resources, importlib.metadata and their backports (importlib_resources, importlib_metadata). Some useful APIs are also provided by packaging (e.g. requirements and version parsing). Users should refrain from new usage of pkg_resources and should work to port to importlib-based solutions.

using python 3.12+ importlib

import importlib.metadata

def list_installed_packages():
    distributions = importlib.metadata.distributions()
    installed_packages = []
    for dist in distributions:
        args = (dist.metadata['Name'], dist.version)
        installed_packages.append(args)
    installed_packages.sort()  # Sort the packages by name
    for package_name, version in installed_packages:
        print(f"{package_name}=={version}")

if __name__ == "__main__":
    list_installed_packages()
1
  • Thanks for this answer, a couple of changes and it now replaces pkg_resources.working_set for my auto module installer. Handy as Python 3.12+ is killing that off. Commented Mar 21 at 18:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.