flake8-print icon indicating copy to clipboard operation
flake8-print copied to clipboard

what is this for?

Open spaceone opened this issue 2 years ago • 6 comments

Hello,

it would be nice to know why someone would want to prevent the use of print() ? Maybe you can extend the README file to explain it?

spaceone avatar Jan 11 '23 19:01 spaceone

Same confusion

failable avatar Apr 11 '23 13:04 failable

Someone might use print() for rapid debugging without an IDE or other development tools.

I'm not suggesting this, this is only one motivation of using this flake8 plugin.

JanMalte avatar Apr 26 '23 08:04 JanMalte

If you're building an application that has structure and abstraction around logging, for example log levels, special formatting, perhaps even logging to places that aren't stdout, then print would likely be an error as it wouldn't go through that logging code.

I think that's valuable only for certain applications, however the pprint checks here are potentially more generally useful.

danpalmer avatar Apr 29 '23 11:04 danpalmer

We're using this in our Django apps to force people to use Django's built-in logging feature (which comes with additional features regarding formatting, filtering, logging to a file instead of the console) instead of raw print statements.

paulkuhle avatar May 27 '23 21:05 paulkuhle

I find these lints infuriating and prefer print.

However, here's something to commit to memory next time you run into this!

Dead simple logging

import logging

log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(message)s")

log.info('Hello world')

Output:

Hello world

Logging: More complex / expanded

The downside of logging is the ceremony involved. The best practice I see for logging typically involves:

More in the fold

You also have to set the logging for yourself if you're an upstream developer, e.g. logging.basicConfig() (perhaps to be logging.basic_config() if PEP-8106 takes off). You may need to use argparse to pass in a --log-level or --verbose to tweak the level used in logging.

import argparse
import logging


log = logging.getLogger(__name__)


def setup_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="My app log")
    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
        default=False,
        help="log.debug shortcut",
    )
    parser.add_argument(
        "--log-level",
        action="store",
        default=False,
        choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
        help="Log level",
    )
    return parser


def setup_logging(log_level="INFO") -> None:
    logging.basicConfig(level=log_level)


if __name__ == "__main__":
    parser = setup_parser()
    args = parser.parse_args()
    log_level = args.log_level

    if not log_level and args.verbose:
        log_level = "DEBUG"

    if log_level:
        logging.basicConfig(level=log_level)

    setup_logging(log_level=log_level)

    log.info("Test")

Output:

INFO:main:Test

Logging: Upsides

For the patient, logging is has some things going for it - it can be configured during a downstream user's application initialization:

If the upstream package provides / supports it:

tony avatar Mar 24 '24 16:03 tony

In addition to @tony's helpful comment, remember you can use sys.stdout.write(...) in place of print() for e.g. returning some value to stdout in a CLI. The benefit of this is that it's explicit that you are returning stuff to stdout.

bsima avatar Apr 04 '24 12:04 bsima