Need to strip the comments out of a Python file before sharing it, counting lines or cleaning up AI-generated code? Here are three ways that work — and one popular shortcut that quietly breaks your code.
The first thing most people try is deleting everything after a #:
import re
cleaned = re.sub(r'#.*', '', source)
It looks fine until your code contains a # inside a string. A URL like "https://example.com/#top" gets cut in half, and your file no longer runs:
# before
URL = "https://example.com/#top" # base URL
# after the regex
URL = "https://example.com/
Python's own tokenizer knows the difference between a comment and a string, so use that instead.
The tokenize module splits source code into the same tokens Python itself sees. Drop the COMMENT tokens and put the rest back together:
import io
import tokenize
def strip_comments(source):
tokens = tokenize.generate_tokens(io.StringIO(source).readline)
kept = [tok for tok in tokens if tok.type != tokenize.COMMENT]
return tokenize.untokenize(kept)
with open("app.py") as f:
print(strip_comments(f.read()))
Strings are untouched, so "https://example.com/#top" survives. Two things to know:
untokenize keeps tokens in their original columns, so a trailing comment leaves trailing spaces, and a comment-only line becomes a blank line. Clean up with "\n".join(line.rstrip() for line in result.splitlines()).tokenize keeps them. See method 3.If you just want clean code without writing a script, paste it into the Code Comment Remover. It reads your code the way a parser does, so:
# inside strings and f-strings is never touched# noqa, # type: ignore and the shebang line are kept by defaultPaste your code, click Remove comments, copy the result. 5 free tries, no account needed.
Open the Comment RemoverDeleting docstrings by hand has a catch: if a function's only statement is its docstring, removing it leaves an empty body and a SyntaxError.
def not_implemented_yet():
"""TODO: write this."""
The safe approach is to find docstrings with the ast module (the first statement of a module, class or function that is a string constant) and replace a body that becomes empty with pass. The Comment Remover does exactly this when you tick Remove Python docstrings.
For sharing a snippet, counting real lines of code or shipping a minimal script, yes. For code you'll keep maintaining, keep comments that explain why — business rules, workarounds, links to issues — and only remove the ones that repeat what the code already says. That's common in AI-generated code, and the Code Humanizer removes just those.
re.sub(r'#.*', '', ...) — it breaks strings that contain #.tokenize for a scriptable, standard-library solution.ast, adding pass where a body would become empty.