š Key Concepts Overview
| Concept | One-Line Definition |
|---|---|
try-except-else-finally |
The complete exception-handling block structure |
else (in try block) |
Runs ONLY if no exception occurred in try
|
finally |
Always runs ā exception or not ā used for cleanup |
sys.exc_info() |
Returns details about the exception currently being handled |
traceback module |
Prints the full error traceback (where exactly it failed) |
raise |
Manually triggers an exception |
Regex (re module) |
Pattern matching/searching/extracting from text |
| Metacharacter | Special symbol with reserved meaning in regex (., ^, $, []) |
| Quantifier | Controls how many times a pattern repeats (*, +, ?, {n,m}) |
š§Æ Part 1 ā Exception Handling: Complete Structure
Nested try-except (Two Risky Operations)
try: # outer suspicious code
x = int(input('Enter a number: '))
y = int(input('Enter a number: '))
try: # inner suspicious code
c = x/y
print(c)
except:
print('Division by zero not possible')
except:
print('Incorrect input. Expecting an integer number only')
This works, but nesting try blocks gets messy. Python gives a cleaner way: else.
else ā Runs ONLY If try Succeeds (No Exception)
try:
x = int(input('Enter a number: '))
y = int(input('Enter a number: '))
except:
print('Incorrect input. Expecting an integer number only')
else: # only runs if try block had NO error
try:
c = x/y
print(c)
except:
print('Division by zero not possible')
Why else is better than just stuffing more code in try: It clearly separates "code that might fail" (in try) from "code that should only run if everything succeeded" (in else). Cleaner intent, easier to read.
lst = [73, 0, 6, 17, 0, 38, 10, 0, 47, 27]
try:
print(10/lst[1]) # lst[1] = 0 ā ZeroDivisionError
except:
print('Exception caught')
else:
print('If there is no exception caught, then this block gets executed')
print('Python')
# Output: 'Exception caught' then 'Python' ā else block SKIPPED because an error occurred
try:
print(10/lst[0]) # lst[0] = 73 ā no error
except:
print('Exception caught')
else:
print('If there is no exception caught, then this block gets executed')
print('Python')
# Output: 3.65..., then 'If there is no exception...', then 'Python' ā else block RUNS
finally ā Always Runs, No Matter What
lst = [73, 0, 6, 17, 0, 38, 10, 0, 47, 27]
try:
print(10/lst[1]) # ZeroDivisionError
except:
print('Exception caught')
else:
print('If there is no exception caught, then this block gets executed')
finally:
print('This block of code will always get executed')
# Output: Exception caught ā This block of code will always get executed
# (else is SKIPPED because an error occurred, but finally ALWAYS runs)
The Full Picture:
| Block | When it runs |
|---|---|
try |
Always attempted first |
except |
Only if try raises an error |
else |
Only if try did NOT raise an error |
finally |
ALWAYS ā regardless of error or not |
DevOps relevance for finally: Closing a network connection, releasing a file lock, or cleaning up a temp resource ā things that MUST happen whether the operation succeeded or failed.
š Part 2 ā Debugging Tools for Exceptions
sys.exc_info() ā Get Details About the Current Exception
import sys
lst = [73, 0, 6, 17, 0, 38, 10, 0, 47, 27]
try:
print(10/lst[1])
except:
print(sys.exc_info()) # returns (exception_type, exception_value, traceback_object)
else:
print('If there is no exception caught, then this block gets executed')
finally:
print('This block of code will always get executed')
# Access individual parts:
print(sys.exc_info()[0]) # the exception TYPE, e.g. <class 'ZeroDivisionError'>
print(sys.exc_info()[1]) # the exception MESSAGE, e.g. division by zero
traceback Module ā Print Where Exactly It Failed
import traceback
lst = [73, 0, 6, 17, 0, 38, 10, 0, 47, 27]
try:
print(10/0)
print(lst[42]) # never reached ā error happens above first
except:
print(traceback.print_exc()) # prints the FULL traceback ā file, line number, error type
else:
print('If there is no exception caught, then this block gets executed')
finally:
print('This block of code will always get executed')
sys.exc_info() vs traceback.print_exc():
| Tool | Use case |
|---|---|
except Exception as e: print(e) |
Quick, readable error message |
sys.exc_info() |
Programmatic access to type/value/traceback object |
traceback.print_exc() |
Full human-readable traceback ā best for debugging logs |
# The cleanest, most common production pattern:
try:
x = int(input('Enter a number: '))
y = int(input('Enter a number: '))
print(x/y)
except Exception as e:
print(e) # simple, clear, catches everything with a readable message
šØ Part 3 ā raise ā Manually Triggering Exceptions
# raise keyword is used to raise a user-defined error
try:
a = int(input('Enter your age: '))
if a < 18:
raise Exception # manually trigger an exception
else:
print('Driving license application accepted')
except:
print('Age is less than 18. Not eligible for the DL')
Why use raise instead of just an if-else with print()?
-
raiselets you enforce business rules as actual ERRORS ā which propagate up, can be caught at a higher level, logged consistently, or stop execution entirely - Useful in larger systems where a function needs to signal "something is wrong" to whoever called it, not just print a message and continue
# Compare:
# Without raise ā just a print, program flow continues normally
if a < 18:
print('Age is less than 18') # this is just informational
# With raise ā flow JUMPS to except, treated as a real error
if a < 18:
raise Exception # forces the except block to run
DevOps relevance: Validating config values, environment variables, or API responses ā raise lets you fail fast and loud instead of silently continuing with bad data.
# Practical DevOps example
def validate_port(port):
if port < 1 or port > 65535:
raise ValueError(f'Invalid port: {port}')
return port
try:
validate_port(99999)
except ValueError as e:
print(e)
āļø DevOps / Cloud Use Cases (Exception Handling)
# 1. Cleanup pattern with finally ā close connections regardless of outcome
try:
# connection = connect_to_db()
print('Connected to DB')
# risky_query()
except Exception as e:
print(f'Query failed: {e}')
finally:
print('Closing DB connection') # ALWAYS runs ā connection never left hanging
# 2. else for "only proceed if input was valid"
try:
instance_count = int(input('How many instances to launch? '))
except ValueError:
print('Must be a number')
else:
if instance_count > 10:
print('ā ļø Warning: launching more than 10 instances')
print(f'Launching {instance_count} instances...')
# 3. raise for config validation ā fail fast
def check_region(region):
valid_regions = ['ap-south-1', 'us-east-1', 'eu-west-1']
if region not in valid_regions:
raise ValueError(f'{region} is not a supported region')
return True
try:
check_region('mars-central-1')
except ValueError as e:
print(f'Config error: {e}')
# 4. traceback for production logging
import traceback
try:
# deploy_to_server()
1/0 # simulated failure
except Exception:
error_log = traceback.format_exc()
# write error_log to a log file for later debugging
print('Deployment failed ā error logged')
ā Common Mistakes (Exception Handling)
| Mistake | Issue | Fix |
|---|---|---|
Putting everything in try, nothing in else
|
Mixes "risky" code with "safe, dependent" code | Use else for code that should only run on success |
Forgetting finally for cleanup |
Resources (files, connections) may leak on error | Use finally for guaranteed cleanup |
Using print() instead of raise for real errors |
Program continues with bad data silently | Use raise to stop and signal failure properly |
Bare except: hides the real problem |
Hard to debug ā don't know WHAT failed | Use except Exception as e: print(e) minimum |
Confusing sys.exc_info()[0] and [1]
|
[0] = type, [1] = value/message |
Remember the order: (type, value, traceback) |
šÆ Interview Points (Exception Handling)
"What's the purpose of the
elseblock in try-except?"
ā It runs only when thetryblock completes WITHOUT any exception ā useful for code that depends on the try block succeeding, keeping it separate from the risky code itself."What's the difference between
elseandfinally?"
āelseruns only if NO exception occurred.finallyruns ALWAYS ā exception or not.finallyis for guaranteed cleanup."What does
raisedo?"
ā Manually triggers an exception, which can be caught by anexceptblock ā used to enforce validation rules or signal errors explicitly rather than silently continuing."What does
sys.exc_info()return?"
ā A tuple of(exception_type, exception_value, traceback_object)for the exception currently being handled."Why use
traceback.print_exc()over a simpleprint(e)?"
ā It shows the FULL traceback ā exact file and line number where the error occurred ā much more useful for debugging in logs than just the error message.
š Knowledge Base ā Quick Revision (Exception Handling)
# āā FULL TRY STRUCTURE āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
try:
risky_code()
except SpecificError:
handle_specific()
except Exception as e:
print(e) # catch-all with message
else:
only_if_success() # runs ONLY if no exception
finally:
always_runs() # runs NO MATTER WHAT
# āā DEBUGGING TOOLS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
import sys
sys.exc_info() # (type, value, traceback)
sys.exc_info()[0] # exception type
sys.exc_info()[1] # exception message/value
import traceback
traceback.print_exc() # full traceback, prints directly
traceback.format_exc() # full traceback, returns as string (for logging)
# āā RAISE āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
if condition:
raise Exception # generic
raise ValueError('msg') # specific, with message
š Part 4 ā Regular Expressions (re module)
What Is Regex?
A pattern-matching language used to find, validate, extract, or replace specific patterns in text. In Python, accessed via import re.
DevOps relevance: Parsing log files, validating IP addresses/emails/ports, extracting fields from unstructured text (logs, config files, API responses), sed/grep-style operations but in Python.
The 4 Components of Regex
1. Functions ā match(), search(), findall(), finditer()
2. Metacharacters ā . ^ $ [] | ()
3. Special Sequences ā \w \W \s \S \d \D \b \B
4. Quantifiers ā ? * + {n} {n,m}
š§ Regex Functions
re.match() ā Match ONLY at the Beginning of the String
import re
text = 'India is my country. I love India very much'
pattern = r'India'
res = re.match(pattern, text)
print(res) # <re.Match object; span=(0, 5), match='India'>
pattern = r'In'
res = re.match(pattern, text)
print(res) # matches ā 'In' is still at the start
pattern = r'love' # NOT at the beginning
res = re.match(pattern, text)
print(res) # None ā match() ONLY checks position 0
Get the actual matched text:
res = re.match(r'India ', text)
print(res.group()) # 'India ' ā the matched string itself
re.search() ā Find the FIRST Occurrence ANYWHERE
text = 'India is my country. I love India very much'
pattern = r'India'
res = re.search(pattern, text)
print(res) # finds it ā anywhere in the string, not just the start
text2 = 'india is my country. I love India very much' # lowercase first 'india'
pattern = r'India'
res = re.search(pattern, text2)
print(res) # finds the SECOND 'India' (capital I) ā case-sensitive!
Match Object Attributes
text = 'india is my country. I love India very much'
pattern = r'India'
res = re.search(pattern, text)
print(res.group()) # the matched text itself: 'India'
print(res.span()) # (start, end) tuple ā e.g. (29, 34)
print(res.start()) # just the start index: 29
print(res.end()) # just the end index: 34 (exclusive)
re.findall() ā ALL Occurrences as a LIST of Strings
text = 'India is my country. I love India very much'
pattern = r'India'
res = re.findall(pattern, text)
print(res, type(res)) # ['India', 'India'] <class 'list'>
pattern = r'india' # lowercase ā won't match capital 'India'
res = re.findall(pattern, text)
print(res) # [] ā empty list, case-sensitive, no match
re.finditer() ā ALL Occurrences as MATCH OBJECTS (Iterator)
text = 'We are learning Python. This is Python class. Python is very interesting.'
pattern = r'Python'
res = re.finditer(pattern, text)
for i in res:
print(i) # full match object
print(i.group()) # just the matched text
print(i.span()) # (start, end) for EACH occurrence
findall() vs finditer() ā Key Difference:
| Function | Returns | Gives you span()/start()/end()? |
|---|---|---|
findall() |
List of plain strings | ā No ā just the text |
finditer() |
Iterator of match objects | ā Yes ā full details per match |
š£ Metacharacters
[] ā Character Set
text = 'chcwasj393e*&#^(@babeidbisadjeiesna'
re.finditer(r'a', text) # matches literal 'a' wherever it appears
re.finditer(r'[a]', text) # same as above, set with ONE character
re.finditer(r'[acw]', text) # matches a OR c OR w ā each one individually
re.finditer(r'[1234]', text) # matches any digit 1, 2, 3, or 4
re.finditer(r'[a-z]', text) # matches any lowercase letter a through z
re.finditer(r'[A-J]', text) # matches any uppercase letter A through J
re.finditer(r'[0-9]', text) # matches any digit
re.finditer(r'[A-Za-z0-9]', text) # matches any alphanumeric character
re.finditer(r'[^K]', text) # ^ INSIDE [] means NOT ā matches everything EXCEPT 'K'
re.finditer(r'[^A-Z]', text) # matches everything EXCEPT uppercase letters
ā ļø ^ means two DIFFERENT things depending on context:
| Position | Meaning |
|---|---|
r'^India' (outside []) |
Match at the BEGINNING of the string |
r'[^A]' (inside []) |
Match anything EXCEPT 'A' (negation) |
^ ā Anchor to Start of String
text = 'India is my country. I love India'
pattern = r'^India'
res = re.finditer(pattern, text)
for i in res:
print(i.group(), i.span())
# Only matches the FIRST 'India' ā because it's at position 0
$ ā Anchor to End of String
text = 'This is Python class. Today is Saturday'
pattern = r'Saturday$'
res = re.finditer(pattern, text)
for i in res:
print(i.group(), i.span())
# Matches only if 'Saturday' is the VERY LAST thing in the string
text2 = 'This is Python class. We have class on Saturday and Sunday. Today is Saturday'
pattern = r'Saturday$'
# Only matches the LAST 'Saturday' (the one at the true end) ā not the earlier one
. (Dot) ā Matches ANY Character Except Newline
text = 'This is Python\n class.'
pattern = r'.'
res = re.finditer(pattern, text)
# Matches every character EXCEPT the \n (newline is skipped)
pattern = r's.' # 's' followed by ANY character
text = 'This is\n Python\n class.'
res = re.finditer(pattern, text)
# Matches 's' + next char, e.g., 'si', 'ss' ā but won't match 's' followed by \n
To match a LITERAL dot (not "any character"), escape it with \:
text = 'This. is P.ytho.n\n cla.ss.'
pattern = r'[.]' # inside [] ā . is treated literally
res = re.finditer(pattern, text)
# matches every actual '.' character
pattern = r'\.' # backslash escape ā also treats . literally
res = re.finditer(pattern, text)
# same result as [.] above
Escaping Other Special Characters
text = '$**^*&GGIUGB jd^ibsji&&)71625 nce^i7 bhi 1.03 83.383 hdj'
re.finditer(r'\^', text) # matches literal '^' character
re.finditer(r'\$', text) # matches literal '$' character
re.finditer(r'\.', text) # matches literal '.' character
Rule: Any metacharacter (., ^, $, [, ], etc.) needs a \ before it to be treated as a literal character instead of a special instruction.
š¤ Special Sequences
# \w ā matches alphanumeric characters (A-Z, a-z, 0-9, _)
# \W ā matches everything EXCEPT alphanumeric (opposite of \w)
# \s ā matches whitespace characters ( , \t, \v, \n, \r)
# \S ā matches everything EXCEPT whitespace (opposite of \s)
# \d ā matches digits (0-9)
# \D ā matches everything EXCEPT digits (opposite of \d)
# \b ā matches a WORD BOUNDARY (edge of a word)
# \B ā matches everything EXCEPT a word boundary
text = 'ndhAe82JE 7yt2vj*&(*^*&$*tvhDNDdviuy7t7BDH er8732ubj _ hdude7_ hj83798Y^&^bjno'
re.finditer(r'\w', text) # every letter, digit, underscore
re.finditer(r'\W', text) # every symbol/space ā opposite of \w
re.finditer(r'\s', text) # spaces, tabs, newlines, etc.
re.finditer(r'\S', text) # everything that ISN'T whitespace
re.finditer(r'\d', text) # every digit 0-9
re.finditer(r'\D', text) # everything that ISN'T a digit
Carriage Return \r and Vertical Tab \v
print('python\rHello') # \r moves cursor to START of line ā 'Hello' overwrites 'python'
# Output appears as: Hello (overwrites visually in terminal)
print('python\vHello') # \v vertical tab ā moves down a line, keeps horizontal position
\b ā Word Boundary
text = 'catherine bought a cat and named him Tomcat. The cat loves catherine'
pattern = r'\bcat' # matches 'cat' ONLY at the start of a word
res = re.finditer(pattern, text)
# Matches: 'cat' (standalone), 'cat' (in 'cat'), but NOT the 'cat' inside 'Tomcat' (mid-word)
# catherine ALSO matches because 'cat' is at the start of that word too!
pattern = r'\Bcat' # matches 'cat' ONLY when NOT at a word boundary (mid-word)
res = re.finditer(pattern, text)
# Matches the 'cat' INSIDE 'Tomcat' only
pattern = r'\bcat\b' # 'cat' as a COMPLETE, standalone word only
res = re.finditer(pattern, text)
# Matches ONLY the standalone word 'cat' ā not 'catherine', not 'Tomcat'
This is the key pattern for "find the exact word, not a substring of a longer word."
š | ā OR Operator
text = 'xyz.com abc.net xyz@gmail.com xyz.in abc.com abc.gov'
pattern = 'com|gov|in' # matches 'com' OR 'gov' OR 'in' ā wherever found
res = re.finditer(pattern, text)
for i in res:
print(i)
() ā Groups (Combine Multiple Patterns)
# Match abc.com, abc.gov, abc.in, abc.net, xyz.com, xyz.gov, xyz.in, xyz.net
text = 'xyz.com abc.net xyz@gmail.com xyz.in abc.com abc.gov'
pattern = '(abc|xyz)(.com|.gov|.in|.net)'
res = re.finditer(pattern, text)
for i in res:
print(i)
# Match hat, cat, rat, bat, mat ā two equivalent approaches:
text = 'hat matrbsi jbatsiucatvs ratvdibat mat hat'
# Approach 1 ā character set
pattern = r'[A-Za-z]at'
# matches ANY single letter + 'at'
# Approach 2 ā explicit group of options
pattern = r'(h|r|m|b)at'
# matches EXACTLY h, r, m, or b + 'at' ā more precise/restrictive
š¢ Quantifiers
# {3} ā exactly 3 repetitions
# {3,5} ā minimum 3, maximum 5 repetitions
# ? ā 0 or 1 repetition (optional)
# * ā 0 or MORE repetitions
# + ā 1 or MORE repetitions
text = 'hat hdb726 87tVmatrb1si jbae3tsiu4catvs&^%80ratvdiba3tbjsbihmat bhjbdb hat'
re.finditer(r'[0-9]', text) # every SINGLE digit, one at a time
re.finditer(r'[0-9]{2}', text) # groups of EXACTLY 2 consecutive digits
re.finditer(r'[0-9]{3}', text) # groups of EXACTLY 3 consecutive digits
text2 = 'hat hdb726 7363 373773 8378733 8376t3 6333b77 93 873 8373777 3638273636763'
re.finditer(r'[0-9]{3,5}', text2) # groups of 3 to 5 consecutive digits
# ? ā 0 or 1
text3 = 'bavcsabcxsa'
re.finditer(r'a?', text3) # matches 'a' if present, or empty string otherwise
# * ā 0 or more
text4 = 'bavcsaaabcxsa'
re.finditer(r'a*', text4) # matches runs of 'a's of ANY length (including zero)
# + ā 1 or more
re.finditer(r'a+', text4) # matches runs of 'a's ā but only where at least ONE exists
? vs * vs + ā Quick Comparison:
| Quantifier | Min | Max | Example match on 'aaa'
|
|---|---|---|---|
? |
0 | 1 |
'a' (just one, or none) |
* |
0 | ā |
'aaa' (the whole run, or empty) |
+ |
1 | ā |
'aaa' (the whole run, requires ā„1) |
āļø DevOps / Cloud Use Cases (Regex)
import re
# 1. Validate an IP address pattern (basic)
text = 'Server connected from 192.168.1.105 on port 8080'
pattern = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
ip = re.search(pattern, text)
print(ip.group()) # '192.168.1.105'
# 2. Extract all ERROR lines from a log
log = 'INFO: started\nERROR: disk full\nINFO: retry\nERROR: connection lost'
errors = re.findall(r'ERROR:.*', log)
print(errors) # ['ERROR: disk full', 'ERROR: connection lost']
# 3. Extract port numbers from config text
config_text = 'app_port=8080, db_port=5432, cache_port=6379'
ports = re.findall(r'\d+', config_text)
print(ports) # ['8080', '5432', '6379']
# 4. Validate email format (basic pattern)
email = 'devops.engineer@company.com'
pattern = r'^[\w.]+@[\w]+\.[a-z]+$'
match = re.match(pattern, email)
print('Valid email' if match else 'Invalid email')
# 5. Extract resource names matching naming convention (env-service-number)
text = 'Resources: prod-web-01, staging-db-02, prod-cache-03'
pattern = r'\w+-\w+-\d{2}'
resources = re.findall(pattern, text)
print(resources) # ['prod-web-01', 'staging-db-02', 'prod-cache-03']
# 6. Find lines starting with a timestamp pattern in logs
log_line = '2026-06-21 14:32:01 ERROR Connection timeout'
pattern = r'^\d{4}-\d{2}-\d{2}'
ts = re.match(pattern, log_line)
print(ts.group() if ts else 'No timestamp found') # '2026-06-21'
ā Common Mistakes (Regex)
| Mistake | Issue | Fix |
|---|---|---|
Using match() expecting full-string search |
match() only checks from position 0 |
Use search() to find anywhere in the string |
| Forgetting case sensitivity |
'India' ā 'india' in default regex |
Use re.IGNORECASE flag if needed |
Treating . as a literal dot |
. matches ANY character, not just .
|
Escape with \. or use [.]
|
Confusing ^ inside vs outside []
|
Outside = "start of string"; inside = "NOT" | Context matters ā memorize both meanings |
Forgetting r'' raw string prefix |
Backslash sequences may be misinterpreted | Always use r'pattern' for regex |
Using findall() when you need position info |
findall() gives only strings, no span |
Use finditer() for match objects with span/start/end |
\b vs \B mix-up |
\b = word boundary, \B = NOT a word boundary |
\bcat\b for exact word; \Bcat for mid-word matches |
šÆ Interview Points (Regex)
"Difference between
re.match()andre.search()?"
āmatch()only checks for a match at the very beginning of the string.search()scans the entire string and returns the first match found anywhere."Difference between
findall()andfinditer()?"
āfindall()returns a list of matched strings.finditer()returns an iterator of match objects, which gives access tospan(),start(),end()for each match."What does
.mean in regex, and how do you match a literal dot?"
ā.matches any character except a newline. To match a literal., escape it as\.or place it inside a character set[.]."What's the difference between
\band\B?"
ā\bmatches a word boundary (start/end of a word).\Bmatches everywhere that is NOT a word boundary ā useful for finding patterns strictly inside a word."Difference between
*,+, and?quantifiers?"
ā*= 0 or more,+= 1 or more (requires at least one),?= 0 or 1 (optional, single occurrence)."Why use raw strings (
r'...') for regex patterns?"
ā To prevent Python from interpreting backslash sequences (like\n,\b) as escape characters before the regex engine sees them ā ensures the pattern is passed through literally.
š Knowledge Base ā Quick Revision (Regex)
import re
# āā FUNCTIONS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
re.match(pattern, text) # only checks the START of string
re.search(pattern, text) # first match ANYWHERE
re.findall(pattern, text) # ALL matches ā list of strings
re.finditer(pattern, text) # ALL matches ā iterator of match objects
# match object attributes
match.group() # matched text
match.span() # (start, end) tuple
match.start() # start index
match.end() # end index
# āā METACHARACTERS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
. # any character except \n
^ # start of string (outside []) / NOT (inside [])
$ # end of string
[] # character set, e.g. [a-z], [0-9], [A-Za-z0-9]
[^...] # NOT these characters
| # OR
() # grouping
# āā SPECIAL SEQUENCES āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
\w \W # word char / NOT word char
\s \S # whitespace / NOT whitespace
\d \D # digit / NOT digit
\b \B # word boundary / NOT word boundary
# āā QUANTIFIERS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
{n} # exactly n
{n,m} # between n and m
? # 0 or 1
* # 0 or more
+ # 1 or more
# āā ALWAYS USE RAW STRINGS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
pattern = r'\d+' # ā
raw string for regex patterns
šļø Practice Questions
Easy
- Write a
try-except-else-finallyblock that asks for two numbers, divides them, and demonstrates all 4 blocks running (success case) ā print a distinct message in each. - Use
re.findall()to extract all digits from the string:'Server-01 has 8 CPUs and 32 GB RAM, port 8080'. - Write a regex pattern using
\bto find the standalone word'log'in the text:'log file blogger logger log'(should match only the exact word'log', not'blogger'or'logger').
Medium
- Write a function
safe_divide(a, b)that usesraise ValueErrorifbis zero, instead of letting Python's naturalZeroDivisionErrorhappen. Catch it with atry-exceptand print a custom message. - Given a log string with multiple lines, use
re.findall()with the patternr'ERROR:.*'to extract all error messages. Then usefinditer()on the same pattern to also print thespan()of each match. - Write a regex pattern that extracts all valid AWS-style resource tags in this format:
env-service-number(e.g.,prod-web-01) from a string containing mixed text.
DevOps-Focused
-
Robust Deployment Function: Write a function
deploy(version)that:- Uses
tryto attempt the "deployment" (simulate with1/int(version)) - Uses
exceptto catch and print errors - Uses
elseto print "Deployment successful" only if no error occurred - Uses
finallyto always print "Deployment process finished"
- Uses
Test it with deploy(2) and deploy(0).
- Log Parser with Regex: Given this log data:
log_data = '''2026-06-20 10:15:32 INFO Service started
2026-06-20 10:16:45 ERROR Connection refused on port 5432
2026-06-20 10:17:02 WARN High memory usage 85%
2026-06-20 10:18:10 ERROR Disk space critical'''
Use regex to: (a) extract all timestamps using pattern r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', (b) extract all ERROR messages using r'ERROR.*', (c) count total ERROR occurrences using len() on the findall() result.
Top comments (0)