15

I don't want "print" statements in our Python modules, because we will be using a logger.

I'm trying to generate a script to check modules with pylint. However, pylint currently does not detect this as a warning or error.

I want to detect "print" invocations as an error or a warning in accordance with our internal Python programming standard.

How can I achieve this?

moylop260
  • 1,288
  • 2
  • 13
  • 20

4 Answers4

16

flake8 has a flake8-print plugin specifically for the task:

flake8-print

Check for Print statements in python files.

DEMO:

$ cat test.py
s = "test"
print s

$ flake8 test.py
test.py:2:1: T001 print statement found.
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • 1
    Shameless plug, but flake8-print has some dependencies that made it unusable in one of projects I was working on. I found this thread though and created my own package that detects print statements: [NoPrint](https://pypi.org/project/noprint/). No dependencies outside of what's already included with basic Python installation. Should be working on Linux, Mac and Windows with Py >= 3.7. – Crad Mar 08 '23 at 14:34
9

If for some reason you don't want to use flake8-print as suggested by @alecxe you can roll your own using the ast module - which makes use of Python's compiler to parse the file so you can reliably find print (instead of lines just starting with print):

Code:

import ast

with open('blah.py') as fin:
    parsed = ast.parse(fin.read())

for node in ast.walk(parsed):
    if isinstance(node, ast.Print):
        print 'print at line {} col {}'.format(node.lineno, node.col_offset)

blah.py:

def print_test():
    print 'hello'

print 'goodbye'

Output:

print at line 4 col 0
print at line 2 col 1

You can use os.walk or os.listdir or whatever's most suitable if you wish to navigate a folder or subfolder.

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Nice alternative! FYI, [`flake8-print`](https://github.com/JBKahn/flake8-print/blob/master/flake8_print.py) uses regex-approach. – alecxe Aug 11 '14 at 18:40
  • My 20 cents I make for detects a "import pdb" setence too: https://gist.github.com/moylop260/10f3e5c7e1c3acfa0ffb – moylop260 Aug 15 '14 at 18:23
  • 1
    Cool, I wrote flake8-print mostly because we needed something at work. I didn't know about ast. I'm going to take a look at this when I have time. – Joseph Kahn Sep 27 '14 at 21:38
  • @JosephKahn, the problem with regex in flake8-print is with setence print but not print. Example: "comment with word print bad for flake8-print". Can you give me your repository and I can make a PR – moylop260 Oct 18 '14 at 20:45
  • @JosephKahn, Oh cool, I saw this commit change: https://github.com/JBKahn/flake8-print/commit/a0c09442f8d7945eb2afe2bba8fa567434a2f143 – moylop260 Oct 18 '14 at 20:51
  • @moylop260 Ya, I'll take a look at making a non-regex change to flake8-debugger as well, just got pretty busy with classes. – Joseph Kahn Oct 18 '14 at 22:56
  • 1
    FYI now pylint add support to detect print sentence with enable E1601 – moylop260 Nov 29 '14 at 16:36
  • @moylop260 the question is about disabling `print` in favour to logging for example. E1601 is about disabling `print` statements in favour to `print` function. It doesn't warn when you use `print` function. – quasiyoke Jan 06 '18 at 01:49
  • Checking for `isinstance(node, ast.Print)` won't work with newer versions. For Python 3 use `node.__dict__.get("id") == "print"` instead. – thlik Jun 08 '21 at 21:24
1

There is also Ruff, which implements the same flake8-print rules.

Using this simple one line file.

print("Hello print!")

Can be quickly checked for print statements with ruff by selecting the T rules.

(venv) PS G:\Testing> ruff test.py --select T
test.py:1:1: T201 `print` found
Found 1 error.

For a more permanent way to enable the rules, you can check the different to configure ruff.

Lemon
  • 140
  • 1
  • 3
  • 13
0

Not perfect: lines like 'print_something()' would be detected, too. But most cases should be catched with this:

import os
import sys

for root, dirs, files in os.walk(sys.argv[1]):
    dirs.sort()
    for file in files:
        file=os.path.join(root, file)
        for i, line in enumerate(open(file)):
            line=line.strip()
            if line.startswith('print'):
                print file, i, line
guettli
  • 25,042
  • 81
  • 346
  • 663