Python › Programming Fundamentals
Functions and error handling
Two ideas finish the fundamentals and turn loose scripts into real tools. Functions let you write a check once and reuse it on thousands of inputs. Error handling lets that check survive the messy reality of dead hosts and malformed responses without crashing and losing all your progress.
You'll learn to
- Write a function that takes input and returns a result
- Understand local vs global scope
- Wrap risky code so one failure doesn't kill the script
Functions
A function is a reusable, named block of code.
import requests
def is_alive(url): # def names it; url is a PARAMETER (an input)
try:
r = requests.get(url, timeout=5)
return r.status_code # send a value back to the caller
except requests.RequestException:
return None # couldn't connect
code = is_alive("https://example.com") # CALL it with an ARGUMENT
if code == 200:
print("alive")
Walk through it. def is_alive(url): defines a function taking one parameter, url. return sends a value back to whoever called it — that value is what code receives. You call the function by writing its name with an argument in parentheses. Now you can check liveness on one URL or ten thousand, with the logic written exactly once.
Scope: where variables live
A variable created inside a function exists only inside it — that’s local scope. The r in is_alive above can’t be used outside the function. Variables defined at the top level of your file are global and visible everywhere.
Error handling: surviving the real world
When something goes wrong, Python raises an exception and, by default, crashes the whole script. try/except lets you catch the error and keep going.
import requests
try:
r = requests.get("https://example.com", timeout=5)
r.raise_for_status() # raise an error on 4xx/5xx responses
data = r.json() # may fail if the body isn't JSON
except requests.Timeout:
print("timed out") # handle a specific error
except requests.RequestException as e:
print(f"request failed: {e}") # handle any requests error; e holds details
except ValueError:
print("response wasn't JSON")
finally:
print("done") # always runs, error or not
You put risky code in try, and handle failures in except blocks. You can catch specific errors (a timeout, a non-JSON body) or a general one. as e captures the error object so you can inspect it. finally always runs — useful for cleanup.
Checkpoint
Your scan loops over 5000 URLs. On URL number 3000, one host hangs and times out. Without error handling, what happens — and how does try/except fix it?
Without handling, the exception crashes the whole script at URL 3000 and you lose everything. With try/except around the request, that one host is caught and skipped (logged as failed), and the loop continues to the remaining 2000 URLs.
Try it yourself
Write a function fetch_title(url) that requests a URL with a timeout, and returns the first 60 characters of the response text — but wrapped in try/except so that if the request fails it returns the string "[unreachable]" instead of crashing. Then imagine calling it in a loop over a list of URLs.
Summary
A function packages logic under a name: it takes parameters, does work, and returns a result, so you write a check once and reuse it everywhere. Variables inside a function are local (invisible outside); pass data in via parameters and out via return. Error handling with try/except catches exceptions so one failure doesn’t crash the whole run — essential the moment you loop over many real, messy targets.
Key takeaways
def name(params):defines a function;returnsends a value back.- Local variables live only inside their function — that’s scope.
try/exceptcatches errors so your script survives bad inputs.- Robust tools wrap every risky operation; one dead host shouldn’t end a scan.
Quick quiz
That completes the programming fundamentals. Next module, you put it all to work: the requests library turns Python into a web-testing tool.