The string module provides useful constants and a Template class for simple string substitution. Less common than f-strings, but useful in specific situations.
Character Constants
Pre-defined character sets:
import string
print(string.ascii_lowercase) # abcdefghijklmnopqrstuvwxyz
print(string.ascii_uppercase) # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.ascii_letters) # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.digits) # 0123456789
print(string.hexdigits) # 0123456789abcdefABCDEF
print(string.octdigits) # 01234567
print(string.punctuation) # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
print(string.whitespace) # ' \t\n\r\x0b\x0c'
print(string.printable) # All printable charactersPassword Generation
import string
import secrets
def generate_password(length=16):
"""Generate a secure random password."""
alphabet = string.ascii_letters + string.digits + string.punctuation
return ''.join(secrets.choice(alphabet) for _ in range(length))
print(generate_password()) # e.g., "K#9mP$xL2!qR@nTz"Input Validation
import string
def is_valid_username(username):
"""Check if username contains only allowed characters."""
allowed = string.ascii_letters + string.digits + '_'
return all(char in allowed for char in username)
print(is_valid_username('alice_123')) # True
print(is_valid_username('alice@123')) # FalseString Cleaning
import string
def remove_punctuation(text):
"""Remove all punctuation from text."""
translator = str.maketrans('', '', string.punctuation)
return text.translate(translator)
text = "Hello, world! How's it going?"
print(remove_punctuation(text)) # "Hello world Hows it going"Template Strings
Safe string substitution:
from string import Template
# Basic substitution
t = Template('Hello, $name!')
print(t.substitute(name='Alice')) # Hello, Alice!
# With dictionary
data = {'name': 'Bob', 'city': 'NYC'}
t = Template('$name lives in $city')
print(t.substitute(data)) # Bob lives in NYCSafe Substitute
Handle missing keys gracefully:
from string import Template
t = Template('Hello, $name! Your balance is $balance')
# substitute() raises KeyError for missing keys
try:
t.substitute(name='Alice')
except KeyError as e:
print(f"Missing: {e}")
# safe_substitute() leaves missing keys unchanged
result = t.safe_substitute(name='Alice')
print(result) # Hello, Alice! Your balance is $balanceTemplate Syntax
from string import Template
# $identifier - simple substitution
t = Template('$greeting, $name')
# ${identifier} - for adjacent text
t = Template('${noun}ification')
print(t.substitute(noun='gamif')) # gamification
# $$ - literal dollar sign
t = Template('Price: $$${price}')
print(t.substitute(price='99')) # Price: $99Why Template Over f-strings?
Templates are useful when:
- User-provided templates - safer than eval/exec
- Configuration files - simple substitution syntax
- Internationalization - templates can be stored externally
from string import Template
# User-provided template (safe)
user_template = Template('Dear $name, your order #$order_id is ready.')
result = user_template.substitute(name='Alice', order_id='12345')
# f-strings with user input would be dangerous
# Never do: eval(f"f'{user_input}'")Custom Delimiters
Change the substitution character:
from string import Template
class PercentTemplate(Template):
delimiter = '%'
t = PercentTemplate('Hello, %name!')
print(t.substitute(name='Alice')) # Hello, Alice!Formatter Class
Lower-level formatting control:
import string
formatter = string.Formatter()
# Parse format string
parsed = list(formatter.parse('{name} is {age} years old'))
for literal, field, format_spec, conversion in parsed:
print(f"Field: {field}, Literal: {literal!r}")Practical Example: Email Templates
from string import Template
email_template = Template("""
Dear $name,
Thank you for your purchase of $product.
Your order number is $order_id.
Total: $$${total}
Best regards,
The Team
""")
def send_confirmation(name, product, order_id, total):
body = email_template.substitute(
name=name,
product=product,
order_id=order_id,
total=total
)
print(body)
send_confirmation('Alice', 'Widget Pro', '12345', '99.99')Config File Pattern
from string import Template
import os
config_template = Template("""
database:
host: $DB_HOST
port: $DB_PORT
name: $DB_NAME
""")
# Substitute from environment
config = config_template.safe_substitute(os.environ)Capwords
Titlecase with proper spacing:
import string
text = "hello world example"
# string.capwords handles multiple spaces
print(string.capwords(text)) # "Hello World Example"
# Compare to str.title()
print(text.title()) # "Hello World Example" (preserves spaces)When to Use string Module
Use string constants when:
- Generating random strings
- Validating input characters
- Cleaning/filtering text
- Need a reference set of characters
Use Template when:
- User-provided format strings (security)
- Simple key-value substitution
- External template files
- i18n/l10n scenarios
Use f-strings/format() when:
- Complex formatting needed
- Expressions in templates
- Performance matters
- Developer-controlled templates
The string module fills specific niches—character constants and safe templating—that come up more often than you might expect.
React to this post: