FawltyDeps
FawltyDeps is a command-line tool designed to find undeclared and unused third-party dependencies in Python projects. It analyzes Python code for import statements and compares them against declared dependencies in `pyproject.toml`, `requirements.txt`, `environment.yml`, and `pixi.toml` files. The current version is 0.20.0, with a release cadence of roughly once a month for minor versions.
Common errors
-
fawltydeps: command not found
cause The `fawltydeps` executable is not in your system's PATH, or it was installed in an isolated virtual environment that is not currently active.fixActivate the virtual environment where `fawltydeps` was installed, or ensure its installation directory is in your PATH. Alternatively, use `python -m fawltydeps`. -
ModuleNotFoundError: No module named 'fawltydeps'
cause FawltyDeps was not installed in the current Python environment where you are trying to run it programmatically or via `python -m`.fixRun `pip install fawltydeps` in your active Python environment. -
FawltyDeps reports a dependency as unused in my Conda/Pixi project, but I know it's needed.
cause FawltyDeps focuses on Python import statements. It might flag non-Python dependencies (e.g., system libraries, CLI tools) declared in `environment.yml` or `pixi.toml` as unused if they are not directly imported by Python code.fixThis is often expected behavior for non-Python components. Verify if the dependency is indeed a non-Python package; FawltyDeps' analysis is for Python imports. -
FawltyDeps says 'PIL' is undeclared, but I have 'Pillow' installed in my environment.
cause FawltyDeps v0.20.0+ output distinguishes between the Python import name (e.g., `PIL`) and the PyPI package name (e.g., `Pillow`). You've imported `PIL`, but FawltyDeps is checking for the *package* `Pillow` to be declared.fixEnsure the correct *package name* (e.g., `Pillow`) is explicitly declared in your dependency files (`requirements.txt`, `pyproject.toml`, etc.). FawltyDeps v0.20.0+ will usually suggest the correct package name.
Warnings
- gotcha When analyzing Conda or Pixi projects (v0.18.0+), FawltyDeps might report non-Python dependencies (e.g., system libraries, CLI tools) as 'unused'.
- gotcha FawltyDeps (v0.20.0+) now distinguishes between Python import names (e.g., `PIL`) and PyPI package names (e.g., `Pillow`) in its output, and will suggest package names for undeclared dependencies.
- deprecated Older versions of FawltyDeps (pre-0.13.3) had different logic for discovering Python environments, which could lead to incorrect dependency resolution, especially regarding the current environment or multiple environments.
- gotcha The `--install-deps` option (v0.17.0+) for creating temporary virtual environments now uses `uv` by default if installed, leading to significantly faster operations compared to `pip`.
Install
-
pip install fawltydeps
Imports
- main
from fawltydeps.main import main
Quickstart
import os
import subprocess
import shutil
# --- Setup a dummy project for demonstration ---
project_dir = "my_fawltydeps_example_project"
os.makedirs(os.path.join(project_dir, "src"), exist_ok=True)
# Create a Python file with imports
with open(os.path.join(project_dir, "src", "app.py"), "w") as f:
f.write("import requests\nimport pandas\nfrom os import path\n")
# Create a requirements file with some declared dependencies
with open(os.path.join(project_dir, "requirements.txt"), "w") as f:
f.write("requests==2.31.0\n")
# --- Run FawltyDeps via subprocess ---
print(f"\nRunning fawltydeps in '{project_dir}' to find mismatches...\n")
try:
# Execute the fawltydeps command line tool
result = subprocess.run(
["fawltydeps", "--verbose", "--code", "src", "--deps", "requirements.txt"],
cwd=project_dir,
capture_output=True,
text=True,
check=False # Set to True if you expect a non-zero exit for issues
)
print("FawltyDeps Output:\n")
print(result.stdout)
if result.stderr:
print("FawltyDeps Errors:\n")
print(result.stderr)
except FileNotFoundError:
print("Error: 'fawltydeps' command not found. Please install it with 'pip install fawltydeps'.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# --- Clean up the dummy project ---
if os.path.exists(project_dir):
shutil.rmtree(project_dir)
print(f"\nCleaned up example project directory: '{project_dir}'")