Pylama: one command in front of nine Python linters
Code audit tool for python.
At a glance
- What is it?
- Pylama does not check Python code itself. It wraps pycodestyle, pydocstyle, PyFlakes, Mccabe, Pylint, Radon, eradicate, Mypy and Vulture, and gives them one configuration file, one ignore syntax and one output format. That is the whole idea, and it is also the whole set of trade-offs.
- Who is it for?
- Pylama fits a team that has accumulated several linters over the years and wants one command, one configuration file and one consistent output format in a terminal and in CI, without rewriting the rules.
- 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 123 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A wrapper, not a linter
Pylama is described as a code audit tool for Python, and the description then lists what it wraps, which is the most important thing in the README.
The list is pycodestyle, formerly pep8, pydocstyle, formerly pep257 by Vladimir Keleshev, PyFlakes, Mccabe, Pylint, Radon, eradicate, Mypy and Vulture. Each entry carries the copyright of its author, which is a small sign of how the project treats the tools it drives.
So Pylama itself does not know what a line length is or what a docstring convention is. It runs the checkers, collects their results, and presents them as one list. The value proposition is in the presentation and in the configuration: one command, one set of ignore rules, one output format, and one place to put the options that individual checkers would otherwise each want.
The quickstart shows the whole of it. Running `pylama` recursively checks the current directory, and running `pylama <path_to_directory_or_file>` checks a path. The output is the common output from all the plugins, which is what makes it usable: the individual checkers have different message formats, and Pylama normalises them so that a single ignore rule covers all of them.
The project is MIT licensed, the primary language is Python, the default branch is `develop`, and the last push was on 2026-06-22. There are no GitHub releases, and the changelog lives in the repository as a `Changelog` file rather than in release notes.
One thing to note about the requirements section. The documented Python versions are 3.7, 3.8, 3.9 and 3.10, and for versions below 3.7 the documentation says to install Pylama 7.7.1. It also notes that failing tests on Windows mean the `curses` library is missing, since it supplies the terminal-independent screen painting and keyboard handling for text terminals.
Installation and the extras that decide what you actually get
Pylama is installed with pip, and the extras are the interesting part.
$ pip install pylamaTOML configuration can be enabled optionally:
$ pip install pylama[toml]And the individual checkers can be installed with the library:
$ pip install pylama[mypy]
$ pip install pylama[pylint]
$ pip install pylama[eradicate]
$ pip install pylama[radon]
$ pip install pylama[vulture]Or all of them at once:
$ pip install pylama[all]The packaging metadata in `setup.py` makes the structure explicit. There is an `OPTIONAL_LINTERS` list of pylint, eradicate, radon, mypy and vulture, and the extras are built from it, with an `all` extra that is the whole list, one extra per linter, and a `toml` extra that pulls in `toml>=0.10.2`.
This has a consequence that is easy to miss and expensive to discover. A bare `pip install pylama` gives you a tool that runs whatever the core requirements pull in, and the optional checkers are absent, so the output of `pylama` on the same code is different on a developer machine, in CI, and in a container, depending on what was installed. The repository itself avoids that problem by pinning things: the `Dockerfile` installs the pinned requirement files first and then the package with its test extra, and the `Makefile` creates a virtual environment from `setup.cfg` and the two files under `requirements/`.
The `toml` extra deserves a note. TOML configuration is a separate install rather than a default, which tells you that reading `pyproject.toml` is a dependency the project is willing to make optional because it is only useful for a subset of users.
The command line, and what a group of error codes means
The options are the second place where Pylama earns its keep, and the README prints the full help output.
$ pylama --help
usage: pylama [-h] [--version] [--verbose] [--options FILE] [--linters LINTERS] [--from-stdin] [--concurrent] [--format {pydocstyle,pycodestyle,pylint,parsable,json}] [--abspath]
[--max-line-length MAX_LINE_LENGTH] [--select SELECT] [--ignore IGNORE] [--skip SKIP] [--sort SORT] [--report REPORT] [--hook] [--max-complexity MAX_COMPLEXITY]
[--pydocstyle-convention {pep257,numpy,google}] [--pylint-confidence {HIGH,INFERENCE,INFERENCE_FAILURE,UNDEFINED}]
[paths ...]The options that do the real work are the ones that filter and select. `--linters` with `-l` chooses the checkers, and the documented choices are eradicate, mccabe, mypy, pycodestyle, pydocstyle, pyflakes, pylint and isort, so `pylama -l "pycodestyle,mccabe"` runs exactly those two.
`--ignore` with `-i` and `--select` with `-s` filter the results, and the documentation is specific about how the filters work. You can choose a group of errors like `D`, `E1` and so on, or special errors like `C0312`, so `pylama -i W,E501` ignores every warning and one specific error code.
Two options are worth calling out because they are not standard. `--skip` takes masks rather than paths, and the example is `*/messages.py`, so a file is skipped by name pattern. And `--hook` installs a Git, or Mercurial, hook, which is a way to run the checks on commit without wiring it into a pre-commit framework by hand.
There are also per-checker options, `--pydocstyle-convention` with pep257, numpy and google, and `--pylint-confidence` with HIGH, INFERENCE, INFERENCE_FAILURE and UNDEFINED. The README adds a note that additional options may be available depending on the installed linters, which is the clearest statement of the wrapper model: the option surface grows with what you install.
One configuration file, searched in a defined order
Pylama looks for a configuration file in the current directory, and the search order is documented precisely.
./pylama.ini
./pyproject.toml
./setup.cfg
./tox.ini
./pytest.ini
~/.pylama.iniThe first five are in the current directory, and the last is the global fallback, a file called `.pylama.ini` in the home directory. The `--option` or `-o` argument can be used to specify a configuration file explicitly, and the file the program searches for is also the one the `--options` help text lists, naming pylama.ini, setup.cfg, tox.ini and pytest.ini.
The configuration format is INI, and it has two levels. Pylama searches for sections whose names start with `pylama`, and the `pylama` section configures global options like `linters` and `skip`:
[pylama]
format = pylint
skip = */.tox/*,*/.env/*
linters = pylint,mccabe
ignore = F0401,C0111,E731The other level is per checker, and it is where the options of the wrapped tools live:
[pylama:pyflakes]
builtins = _
[pylama:pycodestyle]
max_line_length = 100So the same file carries both the selection of checkers and the options of each one, which is the convenience, and it is also a second configuration dialect to learn, since each checker has its own option names and its own quirks and they all have to be expressed in this one file.
The `skip` value in the example is a glob mask, which connects the configuration to the `--skip` command line option, and the `ignore` value is a list of codes in the same form the `-i` option takes.
Modelines and noqa: the overrides that travel with the file
Two escape hatches let a file make its own decisions, and both take priority over the configuration file.
The first is the modeline. You can set options for Pylama inside a source file, anywhere in the file, with a format of names and values separated by colons:
# pylama:{name1}={value1}:{name2}={value2}:...The documentation gives two examples. The first ignores warnings except one, with `# pylama:ignore=W:select=W301`, which is the same syntax as the command line filters. The second disables code checking for the current file, with `# pylama:skip=1`.
The second is the familiar one. Just add `# noqa` at the end of a line to ignore it:
def urgent_fuction():
unused_var = 'No errors here' # noqaThe README states that the modeline options have a higher priority than the configuration file, and it is worth being clear about what that means in practice. A file can turn a rule off for itself, and a reviewer has to notice the modeline to know that the rule is not being enforced there. That is a property of any per-file override, and it is the reason a project with a strict style should decide where the policy lives: in the configuration file that everyone can read at once, or in the files themselves where the exceptions are visible only to whoever opens them.
The precedence order that follows from the documentation is: the command line first, then the modeline in the file, then the configuration file, and the noqa comment is a per-line override that sits outside all of that.
The build: setup.py, a Dockerfile, a Makefile and a pre-commit hook
The repository carries the usual Python packaging, and reading it tells you how the project is developed.
The `setup.py` is a small file with a `parse_requirements` helper that reads a requirements file and hands the lines to `pkg_resources.parse_requirements`, and the optional linters are declared in the `OPTIONAL_LINTERS` list. The use of `pkg_resources` is worth noting for anyone maintaining this, because it is the packaging API that setuptools has been deprecating in favour of the newer metadata interface.
The `Dockerfile` is equally short. It starts from `python:3`, copies the `requirements` directory, installs both the runtime requirements and the test requirements, copies the project, and installs it with the `tests` extra.
The `Makefile` has the targets a maintainer actually uses:
t test: $(VIRTUAL_ENV)
@pytest --pylama pylama
@pytest tests
mypy: $(VIRTUAL_ENV)
mypy pylama
docker-test:
docker run --rm -it pylama pytest --pylama pylamaThe `test` target is the notable one, because `pytest --pylama pylama` runs Pylama over Pylama's own source as part of the test suite. The project lints itself with the tool it ships, which is the cheapest possible check that the wrapper handles its own codebase.
The release path is also in the Makefile. The `release` target installs `bumpversion`, runs it with a version level, and then merges `develop` into `master` and pushes, which is the branch layout the repository uses, with `develop` as the default branch and `master` as the release line. The `upload` target builds the source distribution and the wheel with setuptools and pushes them with twine.
There is also a `.pre-commit-hooks.yaml` in the root, which is the file that registers Pylama as a pre-commit hook for the projects that use it, and it complements the `--hook` option that installs a Git hook directly.
Where Pylama is the wrong tool
The limits follow from the wrapper model, and a reviewer should decide about them before the tool is installed everywhere.
The first is the extra dialect. Every wrapped checker has its own configuration format, its own option names and its own error codes, and Pylama asks for all of them to be expressed in one INI file with per-checker sections, while the ignore rules and the modeline syntax are Pylama's own. A team that has to support Pylama's configuration, the checkers' native configurations and a per-file override syntax has three places where a rule can live, and the priority between them is the part that is easy to get wrong.
The second is that the results depend on what is installed. The optional extras are opt-in, so the same command produces a different list of findings on a machine with `pylama[all]` and on one with a bare install, and the only reliable fix is to pin the set, which is what the repository does for itself with the files under `requirements/` and what a team would have to do in its own continuous integration and in its contributor documentation. A tool whose output depends on the installation is a tool whose output needs to be pinned before it can be trusted.
The third is the age of the stated support matrix. The requirements section lists Python 3.7 to 3.10, and the packaging still uses `pkg_resources`, so a project running on a current Python has to verify that the install works before committing to it.
The alternative is to run the checkers directly, each with its own configuration, and to accept that their outputs differ in format. That is more configuration to write and more output to parse, and it is the reason the wrapper exists. The difference in approach is that Pylama optimises for a single command and a single ignore list, while running the tools directly optimises for using each tool exactly as its author intended, with the cost of N configurations and N output formats. A team that has converged on one linter and wants no abstraction at all should skip the wrapper, and a team with five linters and a shared ignore policy should not.
Editorial conclusion
Pylama fits a team that has accumulated several linters over the years and wants one command, one configuration file and one consistent output format in a terminal and in CI, without rewriting the rules. It is the wrong tool for a project that wants a single linter with one configuration format, because a wrapper adds a dialect on top of every checker it drives, and it is the wrong tool if your CI and your developers install different sets of linters, since the optional extras mean the results depend on what is installed. Before adopting it, pin the linter versions in the same way the repository's own `requirements/` directory does, decide where the ignore policy lives, because `noqa` and the modelines override the configuration file, and check the Python versions the documentation claims to support, which stop at 3.10 in the requirements section.
Frequently asked questions
How do I install pylama?
With `pip install pylama`. The optional checkers come as extras, so `pip install pylama[mypy]`, `pip install pylama[pylint]`, `pip install pylama[eradicate]`, `pip install pylama[radon]` and `pip install pylama[vulture]` add one each, `pip install pylama[all]` adds them all, and `pip install pylama[toml]` enables TOML configuration support.
How do I run only some checkers with pylama?
With the `--linters` option, for example `pylama -l "pycodestyle,mccabe"`. The documented choices are eradicate, mccabe, mypy, pycodestyle, pydocstyle, pyflakes, pylint and isort, and the README notes that additional options may be available depending on the installed linters.
How do I ignore errors in pylama?
Globally with `pylama -i W,E501`, which takes groups of codes such as W or E1 or a specific code such as C0312. Per line, add `# noqa` at the end of the line, and per file use a modeline such as `# pylama:ignore=W:select=W301` or `# pylama:skip=1`, and the README states that the modeline options have a higher priority than the configuration file.
Where does pylama look for its configuration file?
In the current directory, in this order: pylama.ini, pyproject.toml, setup.cfg, tox.ini and pytest.ini, with ~/.pylama.ini in the home directory as a global fallback. The --option or -o argument specifies a configuration file explicitly, and sections whose names start with `pylama` are used.
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/klen-pylama)Was this useful?