GitPedia

Deadcode

Find and fix unused Python code using command line.

From albertas·Updated June 19, 2026·View on GitHub·

The same options can be provided in `pyproject.toml` settings file: The project is written primarily in Python, distributed under the GNU Affero General Public License v3.0 license, first published in 2023. Key topics include: auto-fix, code-quality, deadcode, lithuanian, python.

Deadcode Logo

<h2 align="center">Find and Fix Unused Python Code</h2> <p align="center"> <a href="https://github.com/pre-commit/pre-commit"><img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit" alt="pre-commit" style="max-width:100%;"></a> <a href="https://pypi.org/project/deadcode/"><img alt="PyPI" src="https://img.shields.io/pypi/v/deadcode"></a> <a href="https://pepy.tech/project/deadcode"><img alt="Downloads" src="https://static.pepy.tech/badge/deadcode"></a> <a href="https://github.com/albertas/deadcode/blob/main/LICENSE"><img alt="License: AGPLv3" src="https://raw.githubusercontent.com/albertas/deadcode/main/docs/_static/AGPLv3-license.svg"></a> <br/><a href='https://ko-fi.com/V7V21681GD' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi3.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a> </p>

Installation

shell
pip install deadcode

Usage

To see unused code findings:

shell
deadcode .

To see suggested fixes for all files:

shell
deadcode . --fix --dry

To see suggested fixes only for foo.py file:

shell
deadcode . --fix --dry --only foo.py

To fix:

shell
deadcode . --fix

Tune out some of the false positives, e.g.:

deadcode . --exclude=venv,tests --ignore-names=BaseTestCase,*Mixin --ignore-names-in-files=migrations

The same options can be provided in pyproject.toml settings file:

[tool.deadcode]
exclude = ["venv", "tests"]
ignore-names = ["BaseTestCase", "*Mixin"]
ignore-names-in-files = ["migrations"]

Pre-commit hook

Create a .pre-commit-config.yaml file in the root of your project directory, if it doesn't exist, and add the following to the file:

# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
  - repo: https://github.com/albertas/deadcode
    rev: 2.4.1
    hooks:
      - id: deadcode

Command line options

Option                                   TypeMeaning
--fix-Automatically remove detected unused code expressions from the code base.
--dry-Show changes which would be made in files.
--onlylistFilenames (or path expressions), that will be reflected in the output (and modified if needed).
--excludelistFilenames (or path expressions), which will be completely skipped without being analysed.
--ignore-nameslistRemoves provided list of names from the output. Regexp expressions to match multiple names can also be provided, e.g. *Mixin will match all classes ending with Mixin.
--ignore-names-in-fileslistIgnores unused names in files, which filenames match provided path expressions.
--ignore-names-if-inherits-fromlistIgnores names of classes, which inherit from provided class names.
--ignore-names-if-decorated-withlistIgnores names of an expression, which is decorated with one of the provided decorator names.
--ignore-bodies-oflistIgnores body of an expression if its name matches any of the provided names.
--ignore-bodies-if-decorated-withlistIgnores body of an expression if its decorated with one of the provided decorator names.
--ignore-bodies-if-inherits-fromlistIgnores body of a class if it inherits from any of the provided class names.
--ignore-definitionslistIgnores definition (including name and body) if a name of an expression matches any of the provided ones.
--ignore-definitions-if-inherits-fromlistIgnores definition (including name and body) of a class if it inherits from any of the provided class names.
--ignore-definitions-if-decorated-withlistIgnores definition (including name and body) of an expression, which is decorated with any of the provided decorator names.
--no-color-Removes colors from the output.
--count-Provides the count of the detected unused names instead of printing them all out.
--quiet-Does not output anything. Makefile still fails with exit code 1 if unused names are found.
Glossory
  • name - variable, function or class name.
  • body - code block which follows after : in function or class definition.
  • definition - whole class or function definition expression including its name and body.

Rules

CodeNameMessage
DC01unused-variableVariable {name} is never used
DC02unused-functionFunction {name} is never used
DC03unused-classClass {name} is never used
DC04unused-methodMethod {name} is never used
DC05unused-attributeAttribute {name} is never used
DC06unused-nameName {name} is never used
DC07unused-importImport {name} is never used
DC08unused-propertyProperty {name} is never used
DC09unreachable-if-blockUnreachable conditional statement block
DC11empty-fileEmpty Python file
DC12commented-out-codeCommented out code
DC13unreachable-codeCode after terminal statement, e.g. return, raise, continue, break
DCignore-expressionDo not show any findings for an expression, which starts on current line (this code can only be used in # noqa: DC comments)

Ignoring checks with noqa comments

Inline # noqa comments can be used to ignore deadcode checks.
E.g. unused Foo class wont be detected/fixed because # noqa: DC03 comment is used:

python
class Foo: # noqa: DC03 pass

Contributing

  • make check - runs unit tests and other checks using virtual environment.

Rationale

ruff and
flake8 - don't have rules for unused global
code detection, only for local ones F823, F841, F842. deadcode package
tries to add new DCXXX checks for detecting variables/functions/classes/files
which are not used in a whole code base.

deadcode - is supposed to be used inline with other static code checkers like ruff.

There is an alternative vulture package.

Known limitations

In case there are several definitions using the same name - they all wont be
reported if at least one usage of that name is being detected.

Files with syntax errors will be ignored, because deadcode uses ast to
build abstract syntax tree for name usage detection.

It is assumed that deadcode will be run using the same or higher Python version as the
code base is implemented in.

Feature requests

  • Replace .* with only * in regexp matching.
  • Add unused class method detection DC04 check.
  • Add --fix option to automatically remove detected dead code occourencies
  • Add a check for empty python files.
  • Split error codes into DC01, DC02, DC03 for variables, functions, class.
    • Should have different codes for ignoring name and ignoring whole definition (reserved DCxx0 - ignore name, DCxx1 - ignore definition).
    • Allow to disable each check separately using:
      • inline comment.
      • pyproject.toml file
  • Add a check for code in comments.
  • Add target python version option, if specified it will be used for code base check.
  • Add a --depth parameter to ignore nested code.. (To only check global scope use 0).
  • Add options:
    • --ignore-definitions
    • --ignore-definitions-if-inherits-from
    • --ignore-definitions-if-decorated-with
    • --ignore-names-if-inherits-from
    • --ignore-names-if-decorated-with
    • --ignore-bodies-of
    • --ignore-bodies-if-decorated-with
    • --ignore-bodies-if-inherits-from
    • --ignore-definitions
    • --ignore-definitions-if-inherits-from
    • --ignore-definitions-if-decorated-with
      • Question: would it be possible to ignore only certain types of checks for a body, e.g. only variable attributes of TypedDict and still check usage of methods and properties?
      • What expression would allow this type of precission?
  • Distinguish between definitions with same name, but different files.
  • Repeated application of deadcode till the output stops changing.
  • Unreachable code detection and fixing: this should only be scoped for if statements and only limited to primitive variables.
  • Benchmarking performance with larger projects (time, CPU and memory consumption) in order to optimize.
  • --fix could accept a list of filenames as well (only those files would be changed, but the summary could would be full).
    (This might be confusing, because filenames, which have to be considered are provided without any flag, --fix is expected to not accept arguments)
  • pre-commit-hook.
  • language server.
  • DC10: remove code after terminal statements like raise, return, break, continue and comes in the same scope.
  • Add ignore and per-file-ignores command line and pyproject.toml options, which allows to skip some rules.
  • Make sure that all rules are being skipped by noqa comment and all rules react to noqa: rule_id comments.
  • Include package names into code item scope (dot-separated path), e.g. "package1.package2.module.class.method.variable".
  • All options should be able to accept dot-separated path or a generic name, e.g. "marshmallow.Schema" vs "Schema",
    documentation should cleary demonstrate the behaviour/example that "Schema" means "*.Schema".
  • Redefinition of an existing name makes previous name unreachable, unless it is assigned somehow.
  • Check if file is still valid/parsable after automatic fixing, if not: halt the change and report error.
  • Investigate ways of extracting and backporting Python3.10+ ast implementation to lower Python versions.

Release notes

  • v2.4.1:
    • Add --version option to show deadcode version.
    • Use stdout for deadcode output.
  • v2.4.0:
    • Add --only option that accepts filenames only which will be reflected in the output and modified.
      This option can be used with --fix and --fix --dry options as well as for simple unused code detection without fixing.
  • v2.3.2:
    • Add pre-commit hook support.
    • Drop support for Python 3.8 and 3.9 versions, since their ast implementation is lacking features.
  • v2.3.1:
    • Started analysing files in bytes instead of trying to convert them into UTF-8 encoded strings.
    • Improved automatic removal of unused imports.
  • v2.3.0:
    • Add --dry option.
    • Update error codes to use DCXX format instead of DCXXX.

Contributors

Showing top 1 contributor by commit count.

View all contributors on GitHub →

This article is auto-generated from albertas/deadcode via the GitHub API.Last fetched: 6/24/2026