re Module: Compiled Patterns, Named Groups, and FlagsWhen a regex runs inside a tight loop or parses complex text formats, Python's re module lets you pre-compile patterns with re.compile(), add readable inline comments with re.VERBOSE, and extract fields using named capture groups.
Named groups replace brittle positional indexes like match.group(2) with self-documenting dictionary lookups like match.group("level").
Compile complex patterns once at module level so Python parses the regex syntax only once rather than on every function call.
import re
LOG_PATTERN = re.compile(
r'''
^(?P<date>\d{4}-\d{2}-\d{2})\s+ # ISO date
(?P<level>INFO|WARN|ERROR)\s+ # Severity level
(?P<message>.+)$ # Log body
''',
re.VERBOSE,
)
match = LOG_PATTERN.match("2026-11-12 ERROR Database pool exhausted")
if match:
print(match.groupdict())
re.sub() CallbacksInstead of a static replacement string, pass a function to re.sub() to compute each replacement dynamically from the Match object.
def mask_digits(m: re.Match) -> str:
return "*" * len(m.group(0))
print(re.sub(r"\d{4}(?=\d{4})", mask_digits, "Card 411122223333"))
(a+)+$ can freeze your CPU for seconds on non-matching input; keep quantifiers unambiguous..* when you want lazy .*?: r'"(.*)"' grabs from the first quote to the last quote on the line; use r'"(.*?)"' or r'"([^"]*)"'.re.compile() once outside the loop.re.finditer() do compared to re.findall()?re.finditer() yields Match objects lazily one at a time, giving you start/end positions and named groups without building a large list in memory.
re.IGNORECASE (re.I) affect?It makes letter matching case-insensitive ([a-z] matches A-Z). Combine multiple flags using bitwise OR: re.IGNORECASE | re.MULTILINE.
Never parse nested HTML, XML, or JSON with regex. Use dedicated parsers like json, xml.etree.ElementTree, or BeautifulSoup.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.