JBKahn / flake8-print

flake8
MIT License
119 stars 22 forks source link

what is this for? #59

Open spaceone opened 1 year ago

spaceone commented 1 year ago

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?

failable commented 1 year ago

Same confusion

JanMalte commented 1 year ago

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.

danpalmer commented 1 year ago

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.

paulkuhle commented 1 year ago

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.

tony commented 6 months ago

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()`](https://docs.python.org/3.10/library/logging.html#logging.basicConfig) (perhaps to be `logging.basic_config()` if [PEP-8106](https://github.com/metaperl/peps/blob/main/peps/pep-8106.rst) takes off). You may need to use `argparse` to pass in a `--log-level` or `--verbose` to tweak the `level` used in `logging`. ```python 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:

bsima commented 5 months ago

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.