Skip to main content
https://img.shields.io/github/actions/workflow/status/adamchainz/flake8-logging/main.yml?branch=main&style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/flake8-logging.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

A Flake8 plugin that checks for issues using the standard library logging module.

Requirements

Python 3.8 to 3.12 supported.

Installation

First, install with pip:

python -m pip install flake8-logging

Second, if you define Flake8’s select setting, add the L prefix to it. Otherwise, the plugin should be active by default.


Linting a Django project? Check out my book Boost Your Django DX which covers Flake8 and many other code quality tools.


Rules

LOG001 use logging.getLogger() to instantiate loggers

The Logger Objects documentation section starts:

Note that Loggers should NEVER be instantiated directly, but always through the module-level function logging.getLogger(name).

Directly instantiated loggers are not added into the logger tree, so their messages are discarded. This means you’ll never see any messages on such loggers. Use getLogger() to correctly instantiate loggers.

This rule detects any module-level calls to Logger().

Failing example:

import logging

logger = logging.Logger(__name__)

Corrected:

import logging

logger = logging.getLogger(__name__)

LOG002 use __name__ with getLogger()

The logging documentation recommends this pattern:

logging.getLogger(__name__)

__name__ is the fully qualified module name, such as camelot.spam, which is the intended format for logger names.

This rule detects probably-mistaken usage of similar module-level dunder constants:

  • __cached__ - the pathname of the module’s compiled versio˜, such as camelot/__pycache__/spam.cpython-311.pyc.

  • __file__ - the pathname of the module, such as camelot/spam.py.

Failing example:

import logging

logger = logging.getLogger(__file__)

Corrected:

import logging

logger = logging.getLogger(__name__)

LOG003 extra key '<key>' clashes with LogRecord attribute

The extra documentation states:

The keys in the dictionary passed in extra should not clash with the keys used by the logging system.

Such clashes crash at runtime with an error like:

KeyError: "Attempt to overwrite 'msg' in LogRecord"

Unfortunately, this error is only raised if the message is not filtered out by level. Tests may therefore not encounter the check, if they run with a limited logging configuration.

This rule detects such clashes by checking for keys matching the LogRecord attributes.

Failing example:

import logging
logger = logging.getLogger(__name__)

response = acme_api()
logger.info("ACME Response", extra={"msg": response.msg})

Corrected:

import logging
logger = logging.getLogger(__name__)

response = acme_api()
logger.info("ACME Response", extra={"response_msg": response.msg})

LOG004 avoid exception() outside of exception handlers

The exception() documentation states:

This function should only be called from an exception handler.

Calling exception() outside of an exception handler attaches None exception information, leading to confusing messages:

>>> logging.exception("example")
ERROR:root:example
NoneType: None

Use error() instead. To log a caught exception, pass it in the exc_info argument.

This rule detects exception() calls outside of exception handlers.

Failing example:

import logging

response = acme_api()
if response is None:
    logging.exception("ACME failed")

Corrected:

import logging

response = acme_api()
if response is None:
    logging.error("ACME failed")

LOG005 use exception() within an exception handler

Within an exception handler, the exception() method is preferable over logger.error(). The exception() method captures the exception automatically, whilst error() needs it to be passed explicitly in the exc_info argument. Both methods log with the level ERROR.

This rule detects error() calls within exception handlers with an exc_info argument.

Failing example:

try:
    acme_api()
except AcmeError as exc:
    logger.error("ACME API failed", exc_info=exc)

Corrected:

try:
    acme_api()
except AcmeError:
    logger.exception("ACME API failed")

LOG006 redundant exc_info argument for exception()

The exception() method captures the exception automatically, making a truthy exc_info argument redundant.

This rule detects exception() calls within exception handlers with an exc_info argument that is truthy or the captured exception object.

Failing example:

try:
    acme_api()
except AcmeError:
    logger.exception("ACME API failed", exc_info=True)

Corrected:

try:
    acme_api()
except AcmeError:
    logger.exception("ACME API failed")

LOG007 use error() instead of exception() with exc_info=False

The exception() method captures the exception automatically. Disabling this by setting exc_info=False is the same as using error(), which is clearer and doesn’t need the exc_info argument.

This rule detects exception() calls with an exc_info argument that is falsy.

Failing example:

logger.exception("Left phalange missing", exc_info=False)

Corrected:

logger.exception("Left phalange missing")

LOG008 warn() is deprecated, use warning() instead

The warn() method is a deprecated, undocumented alias for warning() warning() should always be used instead. The method was deprecated in Python 2.7, in commit 04d5bc00a2, and removed in Python 3.13, in commit dcc028d924.

This rule detects calls to warn().

Failing example:

logger.warn("Cheesy puns incoming")

Corrected:

logger.warning("Cheesy puns incoming")

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flake8_logging-1.1.0.tar.gz (10.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flake8_logging-1.1.0-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

Details for the file flake8_logging-1.1.0.tar.gz.

File metadata

  • Download URL: flake8_logging-1.1.0.tar.gz
  • Upload date:
  • Size: 10.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for flake8_logging-1.1.0.tar.gz
Algorithm Hash digest
SHA256 266ca72f3f28e863745dd7ce9eabda9cba53e38985fe7d3a4501a6f9a3e82982
MD5 b357fcf9c0984099c01c06dac01b26b4
BLAKE2b-256 f011c5e17b5f797458e0cecd853a1e10ba5bb08e5f40f9fc9b9486356aa33467

See more details on using hashes here.

File details

Details for the file flake8_logging-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: flake8_logging-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for flake8_logging-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 af545d52db49f1dea73a012d2cb4a2360b9b41d231cfd06373f518702dbc3986
MD5 05e27af049a9f7802e95d518d4aa047a
BLAKE2b-256 a2276b066b0a4c418ff5a19ad15af44c8c3c99032a58d6701bfb0b93ab71ea2c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page