FindImports
FindImports extracts Python module dependencies by parsing source files.
It can report names that are imported but not used, and it can generate
module import graphs in ASCII or graphviz or JSON formats.
A distinguishing feature of findimports used to be that it could parse doctest
code inside docstrings.
Note that not all cases are handled correctly, especially if you use
'import foo.bar.baz', or rely on PEP 420 implicit namespace packages.
If you need to find unused imports in your codebase, I recommend flake8_
instead -- it's better maintained and more reliable. For import graphs
consider pydeps_.
.. _flake8: https://pypi.org/project/flake8/
.. _pydeps: https://pypi.org/project/pydeps/
Installation
Use your favorite Python command-line tool installer such as pipx_ or uv_.
Or run it without installing with ::
uvx findimports --help
.. _pipx: https://pypi.org/project/pipx/
.. _uv: https://pypi.org/project/uv/
Module dependency graphs
On larger projects the module graphs tend to be an unreadable mess. You can
make them clearer by post-processing the graph with tred to remove graph
edges representing direct dependencies to modules that you're already
transitively depending on::
uvx findimports -N -q src -d | tred | xdot -
tred is part of graphviz_. xdot_ is a nice interactive graphviz viewer.
.. _graphviz: https://graphviz.org/
.. _xdot: https://pypi.org/project/xdot/
Misc
Home page: https://github.com/mgedmin/findimports
Licence: MIT (https://mit-license.org/)
|buildstatus|_ |coverage|_
.. |buildstatus| image:: https://github.com/mgedmin/findimports/actions/workflows/build.yml/badge.svg?branch=master
.. _buildstatus: https://github.com/mgedmin/findimports/actions
.. |coverage| image:: https://coveralls.io/repos/mgedmin/findimports/badge.svg?branch=master
.. _coverage: https://coveralls.io/r/mgedmin/findimports
Changes
3.0.0 (2025-12-08)
-
-t/--tred to compute a transitive reduction of the import graph.
Somewhat experimental.
-
Bugfix: names getting imported from a package's ``foo/init.py``` were not
being correctly tracked; they instead were treated as imports from an
external package 'foo', while 'foo.init' was shown to be with no incoming
edges.
Backwards incompatible changes: modules named __init__ are now treated
as packages, so instead of foo.__init__ in the output you'll see just
foo.
2.8.0 (2025-12-06)
-l/--levels now works even without using -p. This lets you
collapse subpackages while still seeing modules inside the top-level package.
2.7.0 (2025-11-14)
-
Add support for Python 3.14.
-
Drop support for Python 3.8 and 3.9.
-
Add --quiet/-q to suppress "could not find some.module" warnings.
-
Add --json/-j to produce JSON output.
-
Support glob patterns in --ignore/-I. Make the default ignore
pattern .*.
Backwards incompatible changes: venv is no longer ignored by default. The
Python community has settled on .venv as the default directory name for a
project-local virtual environment, which is now ignored by the new default
ignore pattern.
2.6.0 (2025-06-02)
-
Drop support for Python 3.7.
-
Add --csv/-C output format: pull request 32 <https://github.com/mgedmin/findimports/pull/32>_.
-
Add --search-import/-s command-line option to filter imports by
substring: pull request 33 <https://github.com/mgedmin/findimports/pull/33>_.
2.5.2 (2024-11-27)
-
Bugfix: findimports was treating all imports as relative, just like in the
good old Python 2 days. Oops.
-
When reporting that it couldn't find the source for an imported module,
findimports will now mention the line number that contained the import
statement.
2.5.1 (2024-10-09)
- Add support for Python 3.13.
2.5.0 (2024-05-30)
-
Fixed extension module detection that never worked on Python 3. See pull request 29 <https://github.com/mgedmin/findimports/pull/29>_.
-
Add --attr/-A to add arbitrary graphviz graph attributes <https://graphviz.org/docs/graph/>_ to the output. See pull request 30 <https://github.com/mgedmin/findimports/pull/30>_.
2.4.0 (2024-02-01)
-
Add support for Python 3.12.
-
Change license from GPL to MIT. See issue 27 <https://github.com/mgedmin/findimports/issues/27>_.
-
Add --package-externals/-pE to simplify the module graph.
-
Add --rmprefix PREFIX/-R PREFIX to remove a package prefix from
displayed names.
-
Add --depth N/-D N to ignore import statements nested too deep in the
syntax tree (e.g. in functions or if statements).
2.3.0 (2022-10-27)
-
Rewrote command-line parsing to use argparse. Options that select an action
(--imports/--dot/--names/--unused) now conflict instead of
all but the last one being ignored. See pull request #20 <https://github.com/mgedmin/findimports/pull/20>_.
-
Add support for Python 3.11.
-
Drop support for Python 3.6.
2.2.0 (2021-12-16)
2.1.0 (2021-05-16)
- Add
--ignore flag to ignore files and directories, it can be used multiple
times. See pull request #14 <https://github.com/mgedmin/findimports/pull/14>_.
2.0.0 (2021-05-09)
-
Add support for Python 3.9.
-
Drop support for Python 3.5 and 2.7.
-
Fix a bug where the encoding of Python files was not determined in the
same way as by Python itself. See issue 15 <https://github.com/mgedmin/findimports/issues/15>_. This requires
the use of tokenize.open which is not in Python 2.7.
1.5.2 (2019-10-31)
-
Add support for Python 3.8.
-
Fix a bug where a package/module with a name that is a prefix of another
package/module might accidentally be used instead of the other one (e.g. py
instead of pylab). See issue 10 <https://github.com/mgedmin/findimports/issues/10>_.
1.5.1 (2019-04-23)
- Drop support for Python 3.4.
1.5.0 (2019-03-18)
-
Support Python 3.6 and 3.7.
-
Drop support for Python 2.6 and 3.3.
-
Suppress duplicate import warnings if the line in question has a comment.
1.4.1 (2016-09-28)
- Replace
getopt with optparse. This changes the --help
message as a side effect (#4 <https://github.com/mgedmin/findimports/issues/4>_).
1.4.0 (2015-06-04)
1.3.2 (2015-04-13)
1.3.1 (2014-04-16)
- Added support for relative imports (e.g.
from .. import foo).
1.3.0 (2013-04-10)
1.2.14 (2012-02-12)
1.2.13 (2011-04-18)
- Suppress "not a zipfile" warnings about
*.egg-info files listed in
sys.path.
1.2.12 (2011-04-08)
- Handle zipfile errors when there are plain files that are not zip files
on sys.path.
1.2.11 (2011-03-30)
- Fix 'could not find cPickle' errors on Python 2.6 and newer.
1.2.10 (2010-02-05)
- Ignore 'from future import ...'.
1.2.9 (2009-07-07)
- Fixed broken and uninstallable source distribution by adding a MANIFEST.in.
1.2.8 (2009-07-07)