Introduction
In operations work, checking the availability of web services is a common task. While third-party libraries such as requests are popular, restricted environments sometimes require you to rely only on Python's standard library.
In this lab, you will use Python's standard library module urllib to create a simple connectivity checker. This demonstrates that useful operational tooling can often be built without extra dependencies.
By the end of this lab, you will understand how to:
- Import the
urllib.requestmodule. - Define a function to check a URL.
- Retrieve HTTP status codes (e.g., 200 OK).
- Handle exceptions like server errors or unreachable hosts.
- Display user-friendly status messages.
Import Modules
In this step, you will start by creating a Python script and importing the necessary module. The urllib.request module is Python's built-in tool for opening URLs. Think of it as a web browser (like Chrome or Firefox) that you can control with code instead of a mouse. It allows your script to fetch data from the internet.
This is useful in operations because many systems expose HTTP-based APIs or health endpoints. Even when teams later adopt third-party libraries, understanding the standard-library tools helps you see the underlying request-response model more clearly.
First, ensure you are in the correct directory. Open your terminal and navigate to the project folder:
cd ~/project
Now, create a new Python file named connectivity_check.py using the nano text editor (or any editor you prefer):
nano connectivity_check.py
In Python, before we can use a library, we must import it. Add the following line to the top of your file. We are importing urllib.request to handle the request and urllib.error to handle potential errors later.
import urllib.request
import urllib.error
Press Ctrl+O, then Enter to save the file, and Ctrl+X to exit nano.
You can verify the file content using the cat command:
cat connectivity_check.py
Define Function
Now that we have our imports ready, we need to structure our code. It is best practice to encapsulate logic within functions. This makes the code reusable and easier to test.
Functions are especially valuable in operational scripts because the same action often needs to run against many targets. Once the network check is wrapped in a function, you can call it for different URLs instead of duplicating code.
In this step, you will define a function named check_url that accepts a URL string as an argument.
Open your connectivity_check.py file again:
nano connectivity_check.py
Add the following function definition below your import statements. For now, we will just add a pass statement, which is a placeholder in Python indicating "do nothing". We will fill in the logic in the next steps.
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
## Logic will go here
pass
Save and exit the editor (Ctrl+O, Enter, Ctrl+X).
This structure sets up the foundation. The function check_url takes one parameter, url, which will be the website address we want to test (e.g., "https://www.google.com").
Make Request
In this step, we will implement the core logic to send a request and retrieve the HTTP status code. An HTTP status code of 200 typically means "OK" or success.
At a high level, an HTTP request is a conversation between client and server. Your script is the client. It sends a request to a URL, waits for the server's response, and then inspects metadata such as the status code before deciding what to do next.
We will use urllib.request.urlopen() to open the URL. This function returns a response object, which has a method .getcode() to retrieve the status code.
Open connectivity_check.py:
nano connectivity_check.py
Update your check_url function to look like this. Note that we are adding a timeout of 5 seconds to prevent the script from hanging if the server doesn't respond.
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
## Open the URL with a 5-second timeout
response = urllib.request.urlopen(url, timeout=5)
## Get the status code
status_code = response.getcode()
print(f"Status Code: {status_code}")
Note: At this stage, if the URL is invalid or the server is down, the script will crash because we haven't added error handling yet. We will fix that in the next step.
Save and exit the editor.
Handle Errors
Network programming is unpredictable. Servers go down, DNS lookups fail, and internet connections drop. If urlopen fails, it raises an exception. To make our script robust, we must handle these exceptions using a try...except block.
This distinction between different failure modes matters in real monitoring. A server returning 500 means you reached the server and it reported an internal problem. A URLError often means the request never reached a usable HTTP endpoint at all. Good operators treat those as different classes of incident.
We will handle two specific types of errors:
urllib.error.HTTPError: The server responded, but with an error code (e.g., 404 Not Found, 500 Server Error).urllib.error.URLError: The server could not be reached at all (e.g., no internet, wrong domain).
Think of the try...except block as a safety net. If something goes wrong (like the internet cutting out), the code won't crash and burn. Instead, it falls into the except block, where we can catch it and display a helpful message.
Open connectivity_check.py:
nano connectivity_check.py
Modify the function to wrap the request logic in a try block:
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
try:
## Attempt to open the URL
response = urllib.request.urlopen(url, timeout=5)
status_code = response.getcode()
print(f"Success! Status Code: {status_code}")
except urllib.error.HTTPError as e:
## Server responded with an error (e.g., 404, 500)
print(f"HTTP Error: {e.code}")
except urllib.error.URLError as e:
## Failed to reach the server
print(f"URL Error: {e.reason}")
This code attempts to execute the lines inside the try block. If an error occurs, Python stops executing the try block and jumps to the matching except block.
Save and exit the editor.
Test the Script
In this final step, we will make the script executable by adding a main block that calls our function. This allows us to run the script directly from the terminal.
The if __name__ == "__main__": pattern is a Python convention that separates reusable functions from the code that should run on direct execution. That small design choice makes later reuse easier, because another script can import check_url without automatically triggering the test calls.
We will test it with a known working URL (like https://www.example.com) and you can also try a fake one to see the error handling in action.
Open connectivity_check.py:
nano connectivity_check.py
Add the following code at the bottom of the file:
if __name__ == "__main__":
## Test with a valid URL
target_url = "https://www.example.com"
check_url(target_url)
print("-" * 20)
## Test with an invalid URL to see error handling
invalid_url = "https://www.this-domain-does-not-exist-12345.com"
check_url(invalid_url)
The if __name__ == "__main__": block ensures that this code only runs when the script is executed directly, not when it is imported as a module in another script.
Save and exit the editor.
Now, run your script to see the results:
python3 connectivity_check.py
You should see output similar to this:
Checking connectivity for: https://www.example.com
Success! Status Code: 200
--------------------
Checking connectivity for: https://www.this-domain-does-not-exist-12345.com
URL Error: [Errno -2] Name or service not known
(Note: The exact error message for the invalid URL may vary slightly depending on the network environment).
Summary
In this lab, you have successfully created a network connectivity checker using Python's standard library. You learned how to:
- Import modules: Used
urllib.requestandurllib.error. - Make HTTP requests: Used
urlopento connect to a web server. - Handle Responses: Retrieved HTTP status codes to verify service availability.
- Manage Errors: Implemented
try...exceptblocks to handleHTTPErrorandURLError, making your script robust against network failures.
This skill is fundamental for creating monitoring scripts, health checks, and simple web scrapers in environments where you cannot install external dependencies.



