Build a Weather Checker CLI Tool

Build a Python CLI tool that fetches real weather data for any city.

Introduction

30 Second Summary

You probably check the weather every day on your phone. But have you ever wondered how that data gets to your screen? Behind every weather app is code that asks a server for forecast data and displays it in a way humans can read.

In this project, you will build a command-line weather checker in Python that fetches real forecast data for any city in the world. You will type a city name, and your tool will talk to a weather API and print back the current temperature, wind speed, and conditions.

What You'll Build

Run your script from the terminal, type "London", and instantly see a clean one-line forecast you could show to anyone.

By the end of this project, you'll have:

  • A working command-line tool that fetches real weather data (temperature, wind, conditions) for any city you type in.
  • Hands-on experience calling a real API and parsing JSON responses into useful, readable output.
  • A Python script with proper error handling that prints friendly messages instead of crashing with ugly tracebacks.
  • Secret Mission: Add a 7-day forecast view that shows the week ahead.

Are there any prerequisites?

None. This guide walks you through installing Python, VS Code, and everything else you need from scratch. All you need is a Windows computer and an internet connection.

Before We Start

Before We Start...

Before we dive in, let's lock in what you're about to build and why it matters.

Set Up Your Python Environment

Every Python project starts with two things: the language itself and an editor to write code in. Without these installed on your machine, you cannot run a single line of Python.

In this step, you will install Python 3.14, set up VS Code as your code editor, and grab the requests library that your weather checker needs to talk to the internet.

In this step, get ready to:
  • Install Python 3.14.6 on your Windows machine.
  • Set up VS Code with the Python extension.
  • Install the requests library for making HTTP calls.
Install Python

Python is the programming language your weather checker is written in. Let's check if it's already installed on your machine.

  • Press the Windows key to open your search bar.
  • Type PowerShell and press Enter to open it.
  • Check if Python is already installed by running this command:
python --version

Look at what appears in the terminal and pick the tab that matches what you see.

✔️ I see Python 3.14 or higher

Python 3.14 is already installed and ready to go. You can close PowerShell and skip ahead to the next substep.

ⓧ I see an older version

You have Python installed, but it is an older version that will not work for this project. You need Python 3.14 or higher.

  • Open your browser and go to the Python 3.14.6 download page:
  • https://www.python.org/downloads/release/python-3146/
  • Scroll down to the Files section and click Windows installer (64-bit) (marked as Recommended).
  • Run the downloaded installer.
  • On the very first screen, check the box that says Add python.exe to PATH at the bottom of the window.
  • Click Install Now and wait for the installation to finish.
  • Close PowerShell completely.
  • Open a new PowerShell window (press the Windows key, type PowerShell, press Enter).
  • Run the version check again to confirm the upgrade worked:
python --version

You should now see Python 3.14.6 printed.

Why do I need to open a new PowerShell?

PATH changes from the installer only take effect in new terminal windows. The old PowerShell window still uses the previous PATH, so it would show your old Python version.

ⓧ Command not found or Microsoft Store opens

Python is not installed on your machine yet. On some Windows versions, typing python opens the Microsoft Store instead of running Python. Close the Store if it opened.

  • Open your browser and go to the Python 3.14.6 download page:
  • https://www.python.org/downloads/release/python-3146/
  • Scroll down to the Files section and click Windows installer (64-bit) (marked as Recommended).
  • Run the downloaded installer.
  • On the very first screen, check the box that says Add python.exe to PATH at the bottom of the window.
  • Click Install Now and wait for the installation to finish.
  • Close PowerShell completely.
  • Open a new PowerShell window (press the Windows key, type PowerShell, press Enter).
  • Confirm Python is installed by running:
python --version

You should see Python 3.14.6 printed.

Still seeing the Microsoft Store or an error?

Open the Start menu, search for Manage app execution aliases, and turn off both App Installer: python.exe entries. Then close and reopen PowerShell and try the version check again.

help me fix Python not being recognized in PowerShell after installing

Not sure which tab to pick?

If you saw a version number like Python 3.12.4 or lower, pick the older version tab. If PowerShell showed a red error message or the Microsoft Store popped open, pick the last tab.

Install VS Code

VS Code is a free code editor that gives you syntax highlighting, a built-in terminal, and extensions that make Python development easier.

  • Open your browser and go to:
  • https://code.visualstudio.com
  • Click the large Download for Windows button.
  • Run the downloaded installer and accept the default options.
  • Once installed, press the Windows key, type Visual Studio Code, and press Enter to open it.

VS Code opens with a Welcome tab. Now install the Python extension so VS Code understands your code.

  • Click the Extensions icon in the left sidebar (it looks like four small squares).
  • Type Python in the search bar at the top of the Extensions panel.
  • Click Install on the first result (published by Microsoft).

You should see a blue Disable button where Install used to be. That confirms the extension is active.

Don't see the Extensions icon?

Press Ctrl+Shift+X to open the Extensions panel directly. The icon may be hidden if your sidebar is collapsed.

help me find and install the Python extension in VS Code

Verify your setup and install requests

The requests library is what your weather checker will use to fetch data from the internet. Before installing it, let's confirm Python works inside VS Code's terminal.

  • In VS Code, click Terminal in the top menu bar.
  • Click New Terminal.

A terminal panel appears at the bottom of VS Code. Before you run the next command, what version number do you expect to see?

  • Confirm Python is available in this terminal by running:
python --version

You should see Python 3.14.6 printed. This proves VS Code's terminal can find your Python installation.

  • Install the requests library by running:
pip install requests==2.34.2

What does this command do?

pip is Python's package manager. It downloads and installs libraries from the internet.

requests==2.34.2 tells pip to install exactly version 2.34.2 of the requests library. Pinning the version ensures everyone gets the same behaviour.

You should see output ending with a line like Successfully installed requests-2.34.2.

  • Verify the library is installed correctly by running:
pip show requests

You should see details about the package including Name: requests and Version: 2.34.2.

Seeing 'pip is not recognized'?

This means the Python Scripts folder was not added to your PATH. Try running the command as python -m pip install requests==2.34.2 instead.

If that also fails, re-run the Python installer, choose Modify, and make sure the PATH checkbox is enabled.

help me fix pip not being recognized in my VS Code terminal on Windows

Your environment is ready. Next up, you will write your first lines of Python and make a real API call to fetch weather data.

Make Your First API Call

Your Python environment is ready with requests installed. Now it is time to prove you can actually talk to a real weather API and get data back.

Before building anything fancy, you need to verify that your code can reach the Open-Meteo API and receive a response. This single connection is the foundation everything else in the project builds on.

In this step, get ready to:
  • Create a weather.py script with a function that calls the Open-Meteo forecast API.
  • Run the script and confirm real weather data comes back in the terminal.
Create your weather script

You need a project folder to keep your files organised, and a Python file where your weather-fetching code will live.

  • Switch back to the terminal in VS Code.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create a project folder and move into it by running these commands:
mkdir weather-checker
cd weather-checker
  • Confirm the folder exists by running:
ls

You should see an empty folder listing (or the folder name echoed back by mkdir).

  • Open this folder in VS Code by clicking File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the weather-checker folder, and click Select Folder.
  • Create a new file by clicking File then New File.
  • Type weather.py as the file name and press Enter.

VS Code opens an empty weather.py file ready for editing.

  • Paste the following code into weather.py:
import requests


def get_weather():
    # Define the API endpoint
    url = "https://api.open-meteo.com/v1/forecast"
    # Set query parameters: New York coordinates and current weather variables
    params = {
        "latitude": 40.71,
        "longitude": -74.01,
        "current": "temperature_2m,wind_speed_10m,weather_code",
    }
    # Send the request and print the raw JSON response
    response = requests.get(url, params=params)
    print(response.json())


if __name__ == "__main__":
    get_weather()

What does this code do?

  • import requests loads the HTTP library you installed in Step 1.
  • get_weather() is a function that builds a request to the Open-Meteo forecast API with hardcoded New York coordinates (latitude 40.71, longitude -74.01).
  • The params dictionary tells the API you want three pieces of current weather: temperature, wind speed, and a weather condition code.
  • requests.get(url, params=params) sends an HTTP GET request and .json() converts the response into a Python dictionary.
  • The if __name__ == "__main__" block means "run this when the script is executed directly" and calls your function.
  • Save weather.py by pressing Ctrl+S.

Red underline under import requests?

If VS Code shows a red squiggly line under import requests, it may not be using the correct Python interpreter.

  • Press Ctrl+Shift+P to open the Command Palette.
  • Type Python: Select Interpreter and select the Python 3.14 interpreter where you installed requests.

Help me fix the red underline on my import statement.

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before continuing.

ⓧ I'd like to double check the full code

Here is the complete weather.py at this point:

import requests


def get_weather():
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": 40.71,
        "longitude": -74.01,
        "current": "temperature_2m,wind_speed_10m,weather_code",
    }
    response = requests.get(url, params=params)
    print(response.json())


if __name__ == "__main__":
    get_weather()
Run your script and see real weather data

The moment of truth. Your script is going to reach out across the internet to the Open-Meteo API and pull back real weather data for New York.

  • Open the terminal in VS Code by pressing Ctrl+` (backtick key, usually above Tab).

Before you run the script, what do you think the output will look like? A clean temperature reading, or something else?

  • Run your weather script:
python weather.py

You should see a wall of curly braces, numbers, and keys dumped into the terminal. Something like this:

{'latitude': 40.710052, 'longitude': -74.01, 'current_units': {'time': 'iso8601', 'temperature_2m': '°C', ...}, 'current': {'time': '2026-07-27T14:00', 'temperature_2m': 29.5, 'wind_speed_10m': 12.3, 'weather_code': 2}}

It works. Your code reached the Open-Meteo API and got real weather data back. But reading this raw JSON blob is painful.

Why is the output so messy?

APIs return data in JSON format (JavaScript Object Notation). JSON is great for machines to read but terrible for humans.

The raw response contains metadata about units, coordinates, and timezone alongside the actual weather values. In the next step, you will extract only the values you care about and format them for human eyes.

Seeing ModuleNotFoundError: No module named 'requests'?

This means Python cannot find the requests library. Make sure you installed it in Step 1.

  • Run pip install requests==2.34.2 in your terminal to install it.
  • If you have multiple Python versions, try python -m pip install requests==2.34.2 instead.

Help me fix ModuleNotFoundError for requests.

You have proven the connection works. Your script talks to a real weather API and gets real data back. Next, you will tame that messy JSON into something a human can actually read.

Format the Output for Humans

In the last step, you successfully called the Open-Meteo API and got weather data back. The problem? That raw JSON blob is impossible to read.

Real tools present data clearly. In this step, you will extract the values you need from the JSON and print them in a friendly, human-readable format.

In this step, get ready to:
  • Create a helper function that translates numeric weather codes into readable descriptions.
  • Update your API function to return data instead of printing it.
  • Build a display function that formats temperature, wind, and conditions into one clean line.
Create the weather code translator

The Open-Meteo API returns weather conditions as numeric codes called WMO weather codes. For example, code 0 means "Clear sky" and code 95 means "Thunderstorm".

You will create a function that converts these numbers into text a human can understand.

  • In weather.py, place your cursor on the blank line between import requests and def get_weather():.
  • Add the first part of the describe_weather_code function by pasting this code:
def describe_weather_code(code):
    """Convert WMO weather code to human-readable description."""
    descriptions = {
        0: "Clear sky",
        1: "Mainly clear",
        2: "Partly cloudy",
        3: "Overcast",
        45: "Foggy",
        48: "Depositing rime fog",
        51: "Light drizzle",
        53: "Moderate drizzle",
        55: "Dense drizzle",
        56: "Light freezing drizzle",
        57: "Dense freezing drizzle",
        61: "Slight rain",
        63: "Moderate rain",
        65: "Heavy rain",

What does this code do?

This function uses a dictionary to map each numeric weather code to a human-readable description. When you pass in a number like 0, it looks up the matching string "Clear sky" and returns it.

The dictionary continues with more weather types in the next code block.

  • Continue the dictionary by adding these remaining entries directly below the last line you just pasted:
        66: "Light freezing rain",
        67: "Heavy freezing rain",
        71: "Slight snow",
        73: "Moderate snow",
        75: "Heavy snow",
        77: "Snow grains",
        80: "Slight rain showers",
        81: "Moderate rain showers",
        82: "Violent rain showers",
        85: "Slight snow showers",
        86: "Heavy snow showers",
        95: "Thunderstorm",
        96: "Thunderstorm with slight hail",
        99: "Thunderstorm with heavy hail",
    }
    return descriptions.get(code, "Unknown")

What does the return line do?

The .get(code, "Unknown") method looks up the code in the dictionary. If the code exists, it returns the description. If not, it returns "Unknown" as a safe fallback instead of crashing.

  • Save weather.py.
  • Test your new function by running this command in the terminal:
python -c "from weather import describe_weather_code; print(describe_weather_code(0))"

You should see Clear sky printed in the terminal.

Seeing a SyntaxError or ImportError?

  • Make sure you saved weather.py before running the test command.
  • Check that the dictionary entries all end with a comma, and that the closing } brace lines up with descriptions =.
  • Make sure your terminal is in the same folder as weather.py.

Help me debug my describe_weather_code function

Update get_weather to return data

Right now, get_weather prints the raw JSON directly. You need it to return the data instead, so other functions can process it before displaying.

  • In weather.py, find your existing get_weather function.
  • Replace the entire function with this updated version:
def get_weather(latitude, longitude):
    """Fetch current weather data from Open-Meteo API."""
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": latitude,
        "longitude": longitude,
        "current": "temperature_2m,wind_speed_10m,weather_code",
    }
    response = requests.get(url, params=params)
    return response.json()

What changed here?

  • The function now accepts latitude and longitude as parameters instead of hardcoding New York's coordinates.
  • The last line changed from print(response.json()) to return response.json(), so the data flows to whatever function needs it next.
Display the weather in a readable format

Now you need a function that takes the raw data, pulls out the values you care about, and prints them in a format a human can scan at a glance.

  • Below your get_weather function, add the display_weather function and update the main block by pasting this code:
def display_weather(data, city_name):
    """Display current weather in a readable format."""
    current = data["current"]
    temp = current["temperature_2m"]
    wind = current["wind_speed_10m"]
    code = current["weather_code"]
    condition = describe_weather_code(code)

    print(f"\nWeather for {city_name}:")
    print(f"  Temperature: {temp}C | Wind: {wind} km/h | Condition: {condition}")


if __name__ == "__main__":
    data = get_weather(40.71, -74.01)
    display_weather(data, "New York")

What does this code do?

  • display_weather digs into the current object from the API response and pulls out temperature, wind speed, and weather code.
  • It calls describe_weather_code to turn the numeric code into a readable condition like "Partly cloudy".
  • The main block now passes New York's coordinates to get_weather, stores the result, and hands it to display_weather for formatting.
  • Make sure you deleted the old if __name__ == "__main__": block that previously called get_weather() with no arguments.
  • Save weather.py.

Before you run the script, what do you think the output will look like this time? Will it be raw JSON again, or something different?

  • Run your script to see the formatted output:
python weather.py

You should see a clean, formatted line like this:

Weather for New York:
  Temperature: 24.5C | Wind: 12.3 km/h | Condition: Partly cloudy

Why do my numbers look different from the example?

The temperature and wind values are live data from the Open-Meteo API. Your numbers will reflect the actual current weather in New York at the moment you run the script. The format is what matters, not the exact values.

Still seeing raw JSON or getting an error?

  • If you see a NameError: name 'describe_weather_code' is not defined, make sure the describe_weather_code function is above get_weather in the file.
  • If you see a TypeError about missing arguments, check that your main block passes 40.71, -74.01 to get_weather.
  • Make sure you only have ONE if __name__ == "__main__": block at the bottom of the file.

Help me debug my weather.py script

✔️ Awesome, I've got everything!

Great. Double check you have saved weather.py and your output shows a formatted line with temperature, wind, and condition.

ⓧ I'd like to double check the full code

Your weather.py should contain these sections in order. Scroll up and confirm each one is present:

  • import requests at the top.
  • The describe_weather_code(code) function with the full dictionary of 28 weather codes and the return descriptions.get(code, "Unknown") line.
  • The get_weather(latitude, longitude) function that returns response.json().
  • The display_weather(data, city_name) function that extracts values from data["current"] and prints the formatted line.
  • The if __name__ == "__main__": block calling get_weather(40.71, -74.01) then display_weather(data, "New York").

Your weather tool now speaks human. Next up, you will replace those hardcoded New York coordinates so the user can type any city name and get weather for that location.

Add City Search

Your weather tool now prints clean, readable output for New York. There is one major limitation though. The coordinates are hardcoded directly in the script, so it only works for one city.

A real weather tool lets you check any city in the world. In this step, you will add city search using Open-Meteo's free Geocoding API, which converts a city name into the latitude and longitude coordinates your weather function needs.

In this step, get ready to:
  • Write a search_city function that calls the Geocoding API to convert a city name into coordinates.
  • Update your main block to ask the user for a city name and fetch weather for that location.
Write the search_city function

Open-Meteo provides a separate Geocoding API at a different endpoint from the weather API. You send it a city name, and it returns geographic coordinates you can feed into get_weather.

  • In weather.py, add this new function directly above your existing get_weather function:
def search_city(city_name):
    """Search for a city and return its coordinates and display name."""
    # Call the Open-Meteo Geocoding API
    url = "https://geocoding-api.open-meteo.com/v1/search"
    params = {"name": city_name, "count": 1, "language": "en"}
    response = requests.get(url, params=params)
    data = response.json()

    # Extract coordinates and name from the first result
    location = data["results"][0]
    name = location["name"]
    country = location.get("country", "")
    latitude = location["latitude"]
    longitude = location["longitude"]

    # Build a human-friendly display name
    display_name = f"{name}, {country}" if country else name
    return latitude, longitude, display_name

What does this code do?

  • The function calls https://geocoding-api.open-meteo.com/v1/search with the city name the user typed.
  • count=1 tells the API to return only the top match instead of a list of possibilities.
  • It extracts the latitude, longitude, city name, and country from the first result, then combines the name and country into a readable string like "London, United Kingdom".
  • The function returns three values at once. Python lets you do this with a comma-separated return statement.
  • Save weather.py.
Update main to accept user input

Now you need your main block to ask the user for a city name instead of using hardcoded New York coordinates.

  • In weather.py, scroll to the if __name__ == "__main__": block at the bottom of the file.
  • Find these two lines inside it:
    data = get_weather(40.71, -74.01)
    display_weather(data, "New York")
  • Replace those two lines with the following code:
    # Ask the user which city to check
    city = input("Enter a city name: ").strip()
    latitude, longitude, display_name = search_city(city)
    data = get_weather(latitude, longitude)
    display_weather(data, display_name)

What does this code do?

  • input("Enter a city name: ") pauses the script and waits for the user to type something.
  • .strip() removes any accidental spaces around the city name.
  • The coordinates from search_city flow directly into get_weather, and the display_name goes to display_weather so the output shows which city matched.
  • Save weather.py.

Before you run this, what do you think will happen when you type "London" at the prompt?

  • Run your script by entering this command in the terminal:
python weather.py
  • When the script asks Enter a city name:, type London and press Enter.

You should see formatted weather data for London, United Kingdom. The temperature, wind speed, and condition will reflect London's current weather.

Not seeing weather data for London?

  • If you see KeyError: 'results', double check that the url in search_city is exactly https://geocoding-api.open-meteo.com/v1/search. A typo in the URL returns a response without the results key.
  • If you see NameError: name 'search_city' is not defined, make sure the function is defined above the if __name__ block, not inside it.
  • If you still see New York data, confirm you replaced the old hardcoded lines and saved the file.

Help me debug my search_city function

  • Try a few more cities to confirm it works worldwide. Type Tokyo or Sydney and check that you get different results each time.

✔️ Awesome, I've got everything!

Great. Double check you have saved weather.py and your script responds to any city you type.

ⓧ I'd like to double check the full code

Your weather.py should now contain these sections in order. Scroll up through your file and confirm each is present:

  • import requests at the top.
  • The describe_weather_code function with the full descriptions dictionary.
  • The new search_city function calling the Geocoding API.
  • The get_weather function calling the Forecast API.
  • The display_weather function printing formatted output.
  • The if __name__ == "__main__": block using input(), search_city, get_weather, and display_weather.

Your tool now works for any city on the planet. There is one problem left to solve though. Try typing a nonsense word like asdfghjkl and watch what happens. In the next step, you will add error handling so your tool responds gracefully instead of crashing.

Handle Errors Gracefully

Your weather tool works perfectly when everything goes right. Type a real city and you get a clean forecast.

But what happens when something goes wrong? A typo in the city name, or a dropped internet connection, and Python crashes with an ugly traceback that means nothing to a normal user. Professional software catches these problems and tells the user what went wrong in plain language.

In this step, get ready to:
  • Add try/except blocks and input validation to search_city.
  • Add try/except blocks and status code checks to get_weather.
  • Test error handling with bad inputs to confirm friendly messages appear instead of crashes.
Add error handling to search_city

First, let's see what happens right now when you type a nonsense city name.

Before you run this, what do you think will happen if you type a completely made-up word as the city?

  • Run your script by entering this command in the terminal:
python weather.py
  • When prompted, type asdfghjkl and press Enter.

You see a wall of red text ending in a KeyError. Python crashed because the API returned no results, and the code tried to access a key that does not exist. That is the problem we are fixing now.

The search_city function needs two kinds of protection. It needs to catch network failures (no internet), and it needs to handle the case where the API finds no matching city.

  • In weather.py, find the import requests line at the very top of the file.
  • Add import sys on the line directly below it, so your imports look like this:
import requests
import sys

What is sys?

The sys module gives you access to system-level functions. You will use sys.exit(1) to stop the script cleanly when an error occurs, instead of letting Python crash with a traceback.

  • Now scroll down to the search_city function and find these lines:
    response = requests.get(url, params=params)
    data = response.json()

    location = data["results"][0]
  • Replace those lines with the following error-handling code:
    try:
        response = requests.get(url, params=params)
    except requests.exceptions.ConnectionError:
        print("Could not connect to the geocoding service. Check your internet connection.")
        sys.exit(1)

    data = response.json()

    if "results" not in data or len(data["results"]) == 0:
        print(f"Could not find a city named '{city_name}'. Try a different spelling.")
        sys.exit(1)

    location = data["results"][0]

What does this code do?

The try/except block wraps the API call. If the network is down, Python raises a ConnectionError instead of crashing. The except block catches it and prints a helpful message.

The if statement checks whether the API returned any results. If the results key is missing or the list is empty, it means the city was not found. The script prints a friendly message and exits cleanly with sys.exit(1).

  • Save weather.py.
  • Run the script again and type asdfghjkl when prompted:
python weather.py

This time you see the message: Could not find a city named 'asdfghjkl'. Try a different spelling. No crash, no traceback.

Still seeing a traceback?

Make sure the import sys line is at the top of your file, directly below import requests. Without it, sys.exit(1) will raise a NameError.

Also check that your if statement comes AFTER data = response.json() and BEFORE location = data["results"][0]. The order matters.

Having trouble? Help me debug my search_city error handling

Add error handling to get_weather

The get_weather function makes a separate API call that can also fail. It needs the same network protection, plus a check that the weather service actually returned valid data.

  • In weather.py, scroll down to the get_weather function and find these lines:
    response = requests.get(url, params=params)
    return response.json()
  • Replace those two lines with the following:
    try:
        response = requests.get(url, params=params)
    except requests.exceptions.ConnectionError:
        print("Could not connect to the weather service. Check your internet connection.")
        sys.exit(1)

    if response.status_code != 200:
        print(f"Weather service returned an error (status {response.status_code}).")
        sys.exit(1)

    return response.json()

What does this code do?

The try/except catches network failures, just like in search_city.

The status_code check is different. Even if the network is fine, the API might return an error (like a 400 for bad parameters). Checking that status_code equals 200 confirms the request actually succeeded before you try to parse the data.

There is one more edge case to handle. What if the user just presses Enter without typing a city name?

  • Scroll down to the if __name__ == "__main__": block at the bottom. Find this line:
    city = input("Enter a city name: ").strip()
  • Directly below that line, add this empty-input check:
    if not city:
        print("Please enter a city name.")
        sys.exit(1)
  • Save weather.py.
  • Run the script and press Enter immediately without typing anything:
python weather.py

You see: Please enter a city name. The script exits cleanly instead of sending an empty string to the API.

Script still sends the empty string to the API?

Make sure the if not city: block is directly after the input() line and before the search_city(city) call. If it comes after, the empty string has already been sent.

Need help? Help me fix my empty input check

Test all three error paths

Your script now handles three failure scenarios. Let's confirm each one works correctly.

  • Run the script one more time:
python weather.py
  • Type London and press Enter. You should see the weather for London printed cleanly.
  • Run the script again. This time type asdfghjkl and press Enter. You should see the friendly not-found message.
  • Run the script one last time. Press Enter without typing anything. You should see the empty-input message.

What about the network error?

You can optionally test the ConnectionError path by disconnecting from the internet and running the script with a valid city name. You should see the connection error message. Reconnect your internet when you are done testing.

All three paths produce a clear, human-readable message. No tracebacks, no crashes, no confusion.

✔️ Awesome, I've got everything!

Great. Double check you have saved weather.py and all three error paths produce friendly messages.

ⓧ I'd like to double check the full code

Your weather.py should now contain all the following pieces, in order. Scroll through your file and confirm each section is present:

  • import requests and import sys at the top.
  • The describe_weather_code function with the full WMO code dictionary.
  • The search_city function with a try/except around the API call and an if check for missing results.
  • The get_weather function with a try/except around the API call and a status_code check.
  • The display_weather function (unchanged).
  • The if __name__ == "__main__": block with an empty-input check before calling search_city.

If any section is missing or out of order, scroll up through this step and apply the relevant chunk again.

Your weather tool now behaves like professional software. It tells users what went wrong and how to fix it, instead of dumping a traceback. Next up, you will extend this tool even further in the Secret Mission.

Secret mission

Add a 7-Day Forecast

Your weather tool shows what's happening right now. But what about the rest of the week? In this secret mission, you'll extend your tool to display a 7-day forecast table with daily highs, lows, and conditions.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally on your machine, so there are no ongoing costs. Decide whether to keep your resources, pause them to come back later, or delete them entirely.

Resources you used:

  • weather.py file (your Python script on the Desktop).
  • requests library (installed via pip).
  • Python 3.14 (installed via the Windows installer).
  • VS Code with the Python extension (installed application).

Keep everything running

No action needed. Choose this if you plan to keep building with Python or want to run your weather checker again.

  • Your weather.py file is yours to keep and modify anytime.
  • Try adding more weather variables, or wrap the main block in a loop so you can check multiple cities without restarting the script.
  • Python, VS Code, and the requests library will remain installed and ready for your next project.

Pause - I'll come back to this later

There are no running processes or background services in this project. Nothing is consuming memory or resources while you are away.

  • Your weather.py file stays on disk until you return.
  • Python and VS Code remain installed but idle.
  • No action required. Come back and run python weather.py whenever you are ready.

Delete - I don't want to use this again

Remove all project files and optionally uninstall the tools you installed during this project.

  • Delete the weather.py file by running this command in your VS Code terminal:
del weather.py
  • Uninstall the requests library by running:
pip uninstall requests -y
  • Uninstall Python: press the Windows key, open Settings, then go to Apps and select Installed apps. Search for Python, click the three dots next to it, and select Uninstall.
  • Uninstall VS Code: in the same Installed apps list, search for Visual Studio Code, click the three dots, and select Uninstall.

That's a Wrap!

That's a Wrap!

Nice work! You just built a fully functional command-line weather checker that talks to a real API and presents data like professional software.

You've learned how to:

  • Built a working command-line tool that fetches real weather data from the Open-Meteo API for any city in the world.
  • Made HTTP requests with Python's requests library and parsed JSON responses to extract exactly the data you needed.
  • Added error handling so your tool prints friendly messages instead of crashing with ugly tracebacks.
  • Secret Mission: Extended your tool with a 7-day forecast view that displays a formatted table of upcoming weather conditions.

Ready to quiz yourself?