flake8-print
flake8-print copied to clipboard
what is this for?
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?
Same confusion
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.
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.
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.
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:
- output destination (stdout / console, text file, third party service)
- formatting (
logging.Formatter) - verbosity level
- advanced filtering
If the upstream package provides / supports it:
- granularity at the module-level
- sprinkling of additional context (
LoggerAdapter)
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.