Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

How to check Python files for common coding mistakes

Walks a directory tree parsing each .py file with ast, reporting empty functions, bare try blocks, too many parameters, and empty classes.

Medium Python 3.9+ Jun 28, 2026 Automation & scripting 2 views 0 copies

Python code

35 lines
Python 3.9+
import ast
import os
import sys

def check_file(filepath):
    try:
        with open(filepath) as f:
            code = f.read()
        tree = ast.parse(code, filename=filepath)
    except SyntaxError as e:
        print(f"{filepath}: SyntaxError: {e.msg}")
        return
    
    issues = []
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            if len(node.body) == 1 and isinstance(node.body[0], ast.Pass):
                issues.append(f"{filepath}:{node.lineno} - Empty function '{node.name}'")
            if len(node.args.args) > 5:
                issues.append(f"{filepath}:{node.lineno} - Function '{node.name}' has too many parameters")
        if isinstance(node, ast.ClassDef):
            if not list(ast.iter_child_nodes(node)):
                issues.append(f"{filepath}:{node.lineno} - Empty class '{node.name}'")
        if isinstance(node, ast.Try):
            if not node.handlers and not node.finalbody:
                issues.append(f"{filepath}:{node.lineno} - Bare try block without except/finally")
    for issue in issues:
        print(issue)

if __name__ == "__main__":
    directory = sys.argv[1] if len(sys.argv) > 1 else "."
    for root, dirs, files in os.walk(directory):
        for filename in files:
            if filename.endswith(".py"):
                check_file(os.path.join(root, filename))

Output

stdout
./utils.py:15 - Empty function 'placeholder'
./models.py:42 - Function 'process_data' has too many parameters
./script.py:8 - Bare try block without except/finally

How it works

The script uses ast.parse to build an abstract syntax tree from each Python source file, then walks every node with ast.walk. For each FunctionDef node it checks if the body is just a single pass (empty function) or if the function takes more than 5 positional arguments. ClassDef nodes are tested for zero child nodes, and Try nodes are flagged when they have no handlers and no finalbody. Errors are printed to stdout in a linter-style <file>:<line> - <message> format for easy review.

Common mistakes

  • Forgetting to catch SyntaxError before walking the AST, which crashes the script on malformed files.
  • Checking `not node.handlers` without also checking `not node.finalbody`, missing bare try blocks that only have finally.
  • Using `ast.iter_child_nodes(node)` instead of `list(ast.iter_child_nodes(node))` for empty class detection, causing a false negative.
  • Not filtering out directories like __pycache__ or hidden folders, which can slow down the scan.

Variations

  1. Use `pathlib.Path.rglob('*.py')` for a cleaner directory traversal instead of os.walk.
  2. Add a `--json` flag to output issues as JSON for integration with CI/CD tools.
  3. Extend checks using `mccabe` to flag functions with high cyclomatic complexity.

Real-world use cases

  • Enforce code style rules in a pre-commit hook before every git push.
  • Scan a legacy monorepo for empty placeholder functions left during refactoring.
  • Add to a CI pipeline to prevent new bare try blocks from merging into production.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.