autopep8: a pycodestyle-driven Python formatter for incremental cleanup
A tool that automatically formats Python code to conform to the PEP 8 style guide.
At a glance
- What is it?
- autopep8 rewrites Python files to satisfy the PEP 8 checks that pycodestyle reports, with aggressive and experimental modes that go beyond whitespace. It suits teams that want to fix a specific error code or line range rather than reformat an entire codebase in one pass.
- Who is it for?
- Adopt autopep8 if your team already runs pycodestyle and wants fixes scoped to specific error codes, line ranges or legacy files, because the --select, --line-range and --ignore options let you limit the blast radius of each change. Do not adopt it if you want one canonical formatting of every file regardless of the original layout; that is Black's model, and mixing the two produces churn.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 75 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What autopep8 fixes, and who ends up using it
autopep8 rewrites Python source so it conforms to the PEP 8 style guide. The README is explicit about the mechanism: it uses the pycodestyle utility to determine what parts of the code need formatting, and it can fix most of the formatting issues that pycodestyle reports. That design choice is the whole story of the tool. autopep8 does not have its own opinion about how Python should look; it has a catalogue of transformations mapped to pycodestyle error codes.
The practical consequence is that autopep8 is a repair tool rather than a style authority. If pycodestyle does not flag something, autopep8 generally will not touch it. Teams reach for it in three situations: a legacy file that fails a lint gate and needs to pass without a human reading every line, a pre-commit hook that fixes trailing whitespace and spacing before a reviewer sees the diff, and a one-off cleanup scoped to a range of lines in a large file. The README's example shows the kind of input it targets, including semicolon-chained statements, missing spaces around operators, and a comment that needs wrapping.
It is not aimed at people who want a single canonical layout for a whole repository. The tool preserves far more of the original file than a from-scratch formatter would, which is exactly what makes it safe on old code and unhelpful if your goal is uniformity.
How the pycodestyle pass drives each fix
The flow is a loop, not a single transform. autopep8 runs pycodestyle over the source, gets back a list of reported issues with their error codes, and applies fixes for the codes it knows how to handle. Because one fix can expose or create another issue, the tool repeats the pass. The -p/--pep8-passes option controls how many additional passes are allowed, and the default is infinite, which means autopep8 keeps going until the output stops changing or no further fixes apply.
What gets fixed is governed by the --ignore and --select options. The default ignore list is E226,E24,W50,W690, so those codes are left alone unless you ask for them. --list-fixes prints the codes the version you installed can handle, which is the authoritative answer for your environment rather than a list copied from a blog post. The fix set follows pycodestyle, so upgrading pycodestyle can change what autopep8 is willing to rewrite.
Aggressiveness is a separate axis. Without -a, autopep8 makes whitespace-level changes. With one -a it enables non-whitespace changes, and the README notes that multiple -a flags result in more aggressive changes. The documented invocation for a thorough pass is two of them:
autopep8 --in-place --aggressive --aggressive <filename>--experimental is a third switch for fixes the project has not settled on. The README's own before-and-after example is a good illustration of the boundary: the multiline string in that sample is deliberately left with its original interior indentation, because the tool only reindents actual code.
Installing autopep8 and running a first diff
autopep8 is published on PyPI and the README gives a single install command. It requires pycodestyle, which pip pulls in as a dependency; the project metadata pins pycodestyle >= 2.12.0 and requires Python 3.10 or newer, with a tomli dependency on Python versions below 3.11.
pip install --upgrade autopep8The README suggests considering pip's --user option if you cannot write to the system environment. In a project, the cleaner route is a virtual environment so the pycodestyle version autopep8 sees is the one pinned in your lockfile.
Before letting it write anything, run it in diff mode on one file. -d/--diff prints the diff for the fixed source and leaves the file untouched:
autopep8 --diff --aggressive --aggressive example.pyRead that patch. If the changes are what you expect, apply them in place with -i/--in-place, and add -r/--recursive to walk a directory. The README states that --recursive must be used with --in-place or --diff, so a bare `autopep8 -r .` is not a valid invocation. To scope the work to one class of problem, use --select with a pycodestyle prefix:
autopep8 --in-place --select E4 example.pyThat fixes only the import-related codes. --line-range takes two line numbers and restricts fixes to an inclusive range, which is useful when a file is too large to review as a single diff. --max-line-length defaults to 79 and changes the wrapping threshold. --exit-code changes the return value semantics: by default 0 means no differences and 1 is an error exit, and with the flag a return of 2 means differences exist, which is what you want in a CI check that should fail when a file is unformatted.
Where autopep8 is the wrong tool
The most important limitation is stated by the project's own framing: autopep8 fixes issues that pycodestyle reports. Anything outside that catalogue stays as it is. Two files that both pass pycodestyle can look completely different, because the tool is not trying to make them look the same. If your review process depends on diffs being small and predictable, that is a feature. If it depends on every file having identical quoting, trailing commas and line-breaking decisions, autopep8 will not deliver it, and no combination of flags will, because those decisions are not error codes.
The aggressive modes are where the risk concentrates. The README documents that -a enables non-whitespace changes and that repeating it makes changes more aggressive, and --experimental enables fixes the project has not finalised. Running `--aggressive --aggressive` across a whole repository in one commit makes the resulting diff hard to review, and if something goes wrong there is no rollback flag in the tool; recovery depends on your version control. The README does not document rollback, so treat the diff as the safety net.
There is also a coupling cost. The fix set tracks pycodestyle, so a pycodestyle upgrade in a shared environment can change autopep8's output even when autopep8 itself has not moved. On a codebase where formatting changes are batched and reviewed, that is a surprise waiting to happen. Pin both.
autopep8 vs Black and Ruff: different contracts
The comparison people search for is autopep8 against Black, and the difference is architectural rather than cosmetic. Black is a from-scratch formatter: it parses the file and re-emits it in one canonical style, so two inputs that are semantically identical produce the same output. autopep8 patches the file you have, guided by pycodestyle's reported errors. Black's output is stable across your codebase; autopep8's output depends on what the file already looked like.
That makes them suitable for different jobs. Black is the right choice when you want formatting to stop being a topic in code review and you are willing to accept one large reformatting commit. autopep8 is the right choice when you cannot afford that commit, when you are working inside a file you do not own, or when you want to fix one error code at a time. Running both is possible but produces churn: autopep8 will keep making changes that Black then rewrites, and the ordering rules between them are not something autopep8's README specifies.
Ruff is a third approach, a linter and formatter written in Rust whose formatting is also opinionated in the Black direction. The relevant difference for an autopep8 user is scope: Ruff bundles linting and formatting in one binary, while autopep8 is a single-purpose fixer that delegates the detection step to pycodestyle. If you already run pycodestyle in CI, autopep8 slots in without changing your lint configuration. If you are choosing a toolchain from scratch, the pycodestyle dependency is an extra moving part you would not have with a self-contained formatter.
Integration-wise, autopep8 is invoked as a command-line tool, so editors and IDEs call it as an external formatter. That is why the same questions about VS Code and PyCharm keep coming up: the setup is a path to the executable plus the argument list, not a plugin-specific configuration format.
Maintenance, licence and the cost of upgrading
The repository is not archived, and the last push was on 2026-07-20. The most recent tagged release is v2.3.2 from 2025-01-14, following v2.3.1 in June 2024 and v2.3.0 earlier that month. The gap between the latest tag and the latest push means the repository sees activity that has not yet been cut into a release, so installing from PyPI and installing from the default branch are not the same thing.
Upgrade cost is dominated by the pycodestyle relationship. Since autopep8's behaviour is defined by which pycodestyle codes it fixes, a pycodestyle bump is a behaviour change even when the autopep8 version number does not move. The pyproject.toml floor is pycodestyle >= 2.12.0, and the default --ignore list (E226,E24,W50,W690) is part of the tool's own defaults rather than pycodestyle's. Before upgrading either package, run autopep8 --list-fixes on the old and new versions and compare the output; that is a concrete check that does not require reading the changelog.
The project is MIT licensed, and the source is a single module, autopep8.py, listed under [tool.setuptools] py-modules. That layout matters if you plan to vendor it: a single file with an MIT licence is straightforward to copy into a build, though you still carry the obligation to keep the licence text with it. This is not legal advice; check the LICENSE file in the repository for the exact terms before redistributing.
Editorial conclusion
Adopt autopep8 if your team already runs pycodestyle and wants fixes scoped to specific error codes, line ranges or legacy files, because the --select, --line-range and --ignore options let you limit the blast radius of each change. Do not adopt it if you want one canonical formatting of every file regardless of the original layout; that is Black's model, and mixing the two produces churn. Before rolling it out, run autopep8 --diff on a representative file to see the actual patch, then confirm the pycodestyle version installed in CI matches the one autopep8 depends on, since the fix set follows pycodestyle's error codes.
Frequently asked questions
What is autopep8 and what does it do?
autopep8 automatically formats Python code to conform to the PEP 8 style guide. It uses the pycodestyle utility to determine what parts of the code need formatting and can fix most of the formatting issues pycodestyle reports.
How do I install autopep8?
The README gives one command, pip install --upgrade autopep8, and suggests considering pip's --user option. autopep8 requires pycodestyle, which is installed as a dependency, and requires Python 3.10 or newer.
How do I use autopep8 to fix a file in place?
The README's documented invocation is autopep8 --in-place --aggressive --aggressive <filename>. To preview changes without writing them, use --diff, and add --recursive when running over a directory, since --recursive must be used with --in-place or --diff.
What is the difference between autopep8 and Black as Python auto formatters?
Black reformats a file from scratch into one canonical style, so identical inputs produce identical output. autopep8 instead patches the existing file based on the errors pycodestyle reports, so its result depends on the original layout.
How do I run autopep8 in VS Code?
autopep8 is a command-line tool, so an editor calls it as an external formatter: you point the Python formatting setting at the autopep8 executable and supply the argument list. The README does not document a VS Code extension or a specific setting name.
Is autopep8 good?
It depends on what you need. It reliably fixes most of the formatting issues pycodestyle reports, including whitespace, spacing and comment wrapping, but it does not impose one canonical layout, so two files that both pass pycodestyle can still look different.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hhatto-autopep8)