Network Requests using Standard Library

PythonBeginner
Practice Now

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.request module.
  • 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.request and urllib.error.
  • Make HTTP requests: Used urlopen to connect to a web server.
  • Handle Responses: Retrieved HTTP status codes to verify service availability.
  • Manage Errors: Implemented try...except blocks to handle HTTPError and URLError, 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.