Generate random strings in Python
npx @tessl/cli install tessl/pypi-rstr@3.2.0A comprehensive Python library for generating random strings from various alphabets and regular expressions. rstr provides both simple random string generation and advanced pattern-based string creation, supporting both secure (SystemRandom) and fast (Mersenne Twister) random number generation for different use cases from development testing to cryptographic applications.
pip install rstrimport rstrFor class-based usage:
from rstr import Rstr, RstrBase, SameCharacterError
# Note: Rstr is an alias for Xeger classFor direct imports:
from rstr import rstr, xeger, letters, digits, uppercase, lowercase
# All alphabet functions are available for direct importComplete available imports:
from rstr import (
# Classes
Rstr, # Main class (alias for Xeger)
RstrBase, # Base class
SameCharacterError, # Exception class
# Core functions
rstr, xeger,
# Alphabet functions
printable, letters, uppercase, lowercase, digits, punctuation,
nondigits, nonletters, whitespace, nonwhitespace, normal, word,
nonword, unambiguous, postalsafe, urlsafe, domainsafe
)Simple random string generation:
import rstr
# Generate random string from custom alphabet
result = rstr.rstr('ABC') # Returns string like 'AACAACCB'
# Generate exact length
result = rstr.rstr('ABC', 4) # Returns 4-character string like 'ACBC'
# Generate regex-based string
postal_code = rstr.xeger(r'[A-Z]\d[A-Z] \d[A-Z]\d') # Returns 'R6M 1W5'def rstr(
alphabet: Iterable[str],
start_range: Optional[int] = None,
end_range: Optional[int] = None,
include: Sequence[str] = '',
exclude: Sequence[str] = ''
) -> strGenerates random strings from the specified alphabet.
Parameters:
alphabet: Characters to choose from (string, list, or tuple)start_range: Minimum length (default: 1, or exact length if end_range not specified)end_range: Maximum length (default: 10 if start_range not specified)include: Characters that must appear in the resultexclude: Characters to exclude from alphabetReturns: Random string meeting the specified criteria
Example:
# Range of lengths
rstr.rstr('ABC', 5, 10) # 5-10 character string
# Include specific characters
rstr.rstr('ABC', include='&') # Will contain '&'
# Exclude characters
rstr.rstr(string.digits, exclude='5') # Digits except '5'def xeger(string_or_regex: Union[str, Pattern[str]]) -> strGenerates random strings matching a regular expression pattern.
Parameters:
string_or_regex: Regular expression pattern (string or compiled Pattern)Returns: Random string matching the pattern
Example:
# Canadian postal code
rstr.xeger(r'[A-Z]\d[A-Z] \d[A-Z]\d')
# Email-like pattern
rstr.xeger(r'[a-z]{3,8}@[a-z]{3,8}\.(com|org|net)')All alphabet functions accept the same parameters as rstr():
def printable(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def letters(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def uppercase(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def lowercase(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def digits(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def punctuation(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def nondigits(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def nonletters(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def whitespace(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def nonwhitespace(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def normal(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def word(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def nonword(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def unambiguous(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def postalsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def urlsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str
def domainsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> strExample:
# Generate random email username
username = rstr.letters(5, 12)
# Generate unambiguous identifier
id_code = rstr.unambiguous(8)
# Generate domain-safe string
domain = rstr.domainsafe(3, 15)class RstrBase:
def __init__(self, _random: Random, **custom_alphabets: str) -> NoneBase class for random string generation functionality.
Parameters:
_random: Random number generator instance (required)**custom_alphabets: Custom alphabet definitions as keyword argumentsclass Xeger(RstrBase):
def __init__(self, _random: Random = random, **custom_alphabets: str) -> NoneMain class implementing random string generation from regular expressions and alphabets.
Parameters:
_random: Random number generator instance (default: standard random module)**custom_alphabets: Custom alphabet definitions as keyword argumentsRstr = Xeger # Alias for Xeger classRstr is an alias for the Xeger class. Use either name interchangeably.
Parameters:
_random: Random number generator instance (default: standard random module)**custom_alphabets: Custom alphabet definitions as keyword argumentsExamples:
from random import SystemRandom
from rstr import Rstr, RstrBase
# Using RstrBase (requires explicit random instance)
base_rstr = RstrBase(SystemRandom())
# Using Xeger/Rstr with default random
default_rstr = Rstr() # Uses standard random module
# Cryptographically secure instance
secure_rstr = Rstr(SystemRandom())
# Instance with custom alphabets
custom_rstr = Rstr(vowels='AEIOU', consonants='BCDFGHJKLMNPQRSTVWXYZ')
# RstrBase with custom alphabets (explicit random required)
secure_base = RstrBase(SystemRandom(), hex_chars='0123456789abcdef')def add_alphabet(self, alpha_name: str, characters: str) -> NoneAdds a custom alphabet to the instance and makes it available as a method.
Parameters:
alpha_name: Name for the new alphabet methodcharacters: String of characters for the alphabetImplementation Note:
The add_alphabet method works with the class's __getattr__ implementation to dynamically create methods. When you call a method name that matches an alphabet name, it automatically calls rstr() with that alphabet.
Example:
rs = Rstr()
rs.add_alphabet('odds', '13579')
result = rs.odds(5) # 5-character string from odd digits
# This is equivalent to:
result = rs.rstr('13579', 5)
# You can also add alphabets during instantiation:
rs = Rstr(evens='02468', odds='13579')
even_result = rs.evens(3) # Uses '02468' alphabetdef sample_wr(self, population: Sequence[str], k: int) -> List[str]Samples k random elements with replacement from a population.
Parameters:
population: Sequence of strings to sample fromk: Number of elements to sampleReturns: List of k randomly selected elements (with replacement)
Example:
rs = Rstr()
samples = rs.sample_wr(['A', 'B', 'C'], 5) # e.g., ['A', 'C', 'A', 'B', 'A']All alphabet methods are available on class instances with the same signatures as package-level functions.
All module-level functions (rstr, xeger, alphabet functions) are actually methods of a default Rstr() instance:
# Internal implementation (from rstr.__init__)
_default_instance = Rstr()
rstr = _default_instance.rstr
xeger = _default_instance.xeger
letters = _default_instance.letters
# ... all other alphabet functionsThis means that all module-level functions share the same random state and use the standard random module by default.
class SameCharacterError(ValueError):
passRaised when include and exclude parameters contain the same character(s) in any rstr() call.
When raised:
rstr() or any alphabet function with overlapping include and exclude charactersValueError for standard exception handling patternsExamples:
import rstr
try:
# Single conflicting character
result = rstr.rstr('ABC', include='A', exclude='A')
except rstr.SameCharacterError as e:
print(f"Error: {e}")
# Output: "include and exclude parameters contain same character (A)"
try:
# Multiple conflicting characters
result = rstr.letters(include='XY', exclude='YZ')
except rstr.SameCharacterError as e:
print(f"Error: {e}")
# Output: "include and exclude parameters contain same characters (Y)"For cryptographic applications, use SystemRandom:
from random import SystemRandom
from rstr import Rstr
# Create secure instance
secure_rstr = Rstr(SystemRandom())
# Generate secure password
password = secure_rstr.unambiguous(16)Combine rstr with string formatting:
# Generate email address
email = '{0}@{1}.{2}'.format(
rstr.nonwhitespace(exclude='@'),
rstr.domainsafe(),
rstr.letters(3)
)
# Generate URL
url = 'https://{0}.{1}/{2}?{3}'.format(
rstr.domainsafe(),
rstr.letters(3),
rstr.urlsafe(),
rstr.urlsafe()
)
# Generate postal address
address = """{0} {1}
{2} {3}
{4}, {5} {6}""".format(
rstr.letters(4, 8).title(),
rstr.letters(4, 8).title(),
rstr.digits(3, 5),
rstr.letters(4, 10).title(),
rstr.letters(4, 15).title(),
rstr.uppercase(2),
rstr.digits(5)
)# Instance with custom alphabets
rs = Rstr(
vowels='AEIOU',
consonants='BCDFGHJKLMNPQRSTVWXYZ',
hex_lower='0123456789abcdef'
)
# Use custom alphabets
vowel_string = rs.vowels(5)
consonant_string = rs.consonants(10)
hex_id = rs.hex_lower(8)from typing import Iterable, List, Mapping, Optional, Sequence, Union, Pattern
from random import Random
# Core function signature types
AlphabetType = Iterable[str]
IncludeExcludeType = Sequence[str]
RegexInputType = Union[str, Pattern[str]]
# Internal type definitions (available but not typically needed)
from typing import TypeVar, Protocol
_T = TypeVar('_T')
class _PartialRstrFunc(Protocol):
"""Type definition for dynamically created alphabet methods"""
def __call__(
self,
start_range: Optional[int] = ...,
end_range: Optional[int] = ...,
include: str = ...,
exclude: str = ...,
) -> str: ...# From rstr.rstr_base
from rstr.rstr_base import ALPHABETS
ALPHABETS: Mapping[str, str] # Predefined alphabet mappings
# From rstr.xeger
from rstr.xeger import STAR_PLUS_LIMIT
STAR_PLUS_LIMIT: int = 100 # Maximum repeats for regex * and +pip install rstr# Generate test data with specific constraints
test_usernames = [rstr.letters(3, 20) for _ in range(100)]
test_emails = [f"{rstr.letters(5)}@{rstr.domainsafe()}.com" for _ in range(50)]
# Fuzz testing with problematic characters
fuzz_inputs = [rstr.rstr(string.printable, include=char) for char in '<>&"\'']# Generate realistic-looking dummy data
names = [rstr.letters(4, 12).title() for _ in range(100)]
phone_numbers = [rstr.xeger(r'\(\d{3}\) \d{3}-\d{4}') for _ in range(50)]
social_security = [rstr.xeger(r'\d{3}-\d{2}-\d{4}') for _ in range(25)]