Home / Alt manpages / py3clean(1)

  • py3clean(1)
  • User command
  • linux

Safely remove stale Python 3 bytecode with py3clean

You will remove generated .pyc and .pyo files while keeping the Python source files that produced them. You will also see how the installed command selects a Python version and how Debian package mode narrows the files it considers. Allow about ten minutes for a project directory, or longer if you need to review a system package before deleting anything.

Warning

Py3clean deletes files. The bytecode is normally reproducible, but deletion is not an undoable edit to the filesystem. Back up anything you cannot regenerate, and inspect the target before running the command. Do not start with a broad system path as root.

1. Check the installed command

This guide describes the py3clean shipped by Ubuntu's python3-minimal package on this machine. The installed package is version 3.12.3-0ubuntu2.1. Option details and file-selection behaviour can vary between releases, so check your own version before putting the command in a script.

$ command -v py3clean
/usr/bin/py3clean
$ dpkg-query -W -f='${Package} ${Version}\n' python3-minimal
python3-minimal 3.12.3-0ubuntu2.1
$ py3clean --version
py3clean 3.12.3-0ubuntu2.1
$ py3clean --help
Usage: py3clean [-V VERSION] [-p PACKAGE] [DIR_OR_FILE]

The normal positional argument is a source directory or a Python source file. Passing the name of a bytecode file is a common distraction: py3clean looks for source files and then removes their associated generated files.

2. Clean one project directory

First make a disposable fixture so you can see exactly what is removed. These commands create Python source files and dummy generated files under /tmp; they do not touch your project.

$ demo=/tmp/py3clean-demo
$ mkdir -p "$demo/sub"
$ printf 'value = 1\n' > "$demo/main.py"
$ printf 'value = 2\n' > "$demo/sub/helper.py"
$ touch "$demo/main.pyc" "$demo/main.pyo" "$demo/sub/helper.pyc"
$ find "$demo" -type f -printf '%P\n' | sort
main.py
main.pyc
main.pyo
sub/helper.py
sub/helper.pyc

Run py3clean on the directory. The -v option enables diagnostics, including a count of removed files. The command is normally unprivileged when the directory belongs to you.

$ py3clean -v "$demo"
I: py3clean:155: removed files: 3

Check the result. Source files remain, while the associated classic bytecode files have gone.

$ find "$demo" -type f -printf '%P\n' | sort
main.py
sub/helper.py

In a real tree, py3clean also considers version-tagged files in __pycache__, such as module.cpython-312.pyc. It can remove an empty __pycache__ directory as part of that cleanup. It does not remove the .py file.

3. Limit removal to one Python version

Use -V VERSION when several Python versions share a tree and you want to remove only one version's tagged cache files. The version value is a Python version, not a package name. For example, -V 3.12 selects the cpython-312 magic tag on this installation.

$ mkdir -p "$demo/versions/__pycache__"
$ printf 'value = 3\n' > "$demo/versions/module.py"
$ touch "$demo/versions/py-only.pyc"
$ touch "$demo/versions/__pycache__/module.cpython-312.pyc"
$ touch "$demo/versions/__pycache__/module.cpython-311.pyc"
$ py3clean -V 3.12 -v "$demo/versions"
D: py3clean:78: magic tags to remove: cpython-312
I: py3clean:155: removed files: 1
$ find "$demo/versions" -type f -printf '%P\n' | sort
__pycache__/module.cpython-311.pyc
module.py
py-only.pyc

The untagged py-only.pyc and the Python 3.11 cache remain in this version-filtered example. Without -V, the installed command's default is to remove all associated Python 3 bytecode it finds. Use the filter when another interpreter still needs its cache.

4. Clean files belonging to a Debian package

The -p PACKAGE option asks Debian's package database for files belonging to a package and cleans those files. This is useful after removing a package's generated caches, but it is a system-wide operation. Read the package name carefully and expect to need elevated privileges if the target files are not writable by your account.

$ dpkg-query -L python3-minimal | sed -n '1,12p'
/.
/usr
/usr/bin
/usr/bin/py3clean
/usr/bin/py3compile
/usr/share
/usr/share/doc
/usr/share/doc/python3-minimal
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/py3clean.1.gz
$ py3clean -p python3-minimal -v

Do not add sudo automatically. First confirm the package and review what it owns with dpkg-query -L. If the command reports permission errors for a system package, stop and decide whether the cleanup is necessary. If it is necessary, rerun the exact reviewed command with sudo, preferably during a maintenance window.

You can provide both -p and a directory or file. In that form, py3clean considers only files that are both under the supplied path and recorded as belonging to the package. This intersection is useful for narrowing a package cleanup, but it is not a preview, and it still deletes files.

5. Protect useful output and handle failures

There is no restore command in py3clean. If a generated file matters, copy the source tree or package it before cleaning. Python will recreate import bytecode when it has permission and the runtime chooses to write it, but a read-only deployment or a missing build step can make that assumption unsafe.

For a project, verify the source tree first and keep a rollback copy outside the target:

$ test -d /path/to/project
$ find /path/to/project -type f \( -name '*.py' -o -name '*.pyc' -o -name '*.pyo' \) -print
$ cp -a /path/to/project /path/to/project.before-py3clean
$ py3clean -v /path/to/project
$ python3 -m compileall -q /path/to/project

The final command is a separate verification step. It recompiles readable Python files; it is not part of py3clean, and it may require write access to the project. If the cleanup was accidental, restore the reviewed backup with your normal deployment or file-copy procedure. Do not delete the backup until imports and application tests pass.

If nothing is removed, that can be correct. The command may find no Python source files under the supplied path, the package may own no bytecode there, or a version filter may exclude every cache. Recheck the path, package name and cache tags before changing permissions or using root.

Done means

  • You confirmed the installed py3clean version and read its option syntax.
  • You inspected the target directory or Debian package before running a deleting command.
  • You used an unprivileged project cleanup where possible, and treated -p on system files as an elevated operation.
  • You used -V when another Python version's cache had to remain.
  • Your Python source files and application checks still pass after cleanup.
  • You kept a recovery copy for generated files that could not be recreated safely.