DE EN

APIs & Requests

Communicating with the internet — fetching weather data, understanding APIs, using real data.

60 Min Schwer

Lernziele dieses Kapitels

  • You send HTTP requests with the requests library
  • You process JSON responses from APIs
  • You use API keys safely via environment variables
  • You extend PyBuddy with a weather function

HTTP Requests with requests

With the requests library you fetch data from the internet. requests.get(url) retrieves a webpage or API. The status_code shows whether everything worked.

  • 200 — All OK
  • 404 — Not found
  • 500 — Server error
Python
import requests

# Einfacher GET-Request
url = "https://api.github.com"
response = requests.get(url)

print(f"Status: {response.status_code}")
print(f"Content-Type: {response.headers['Content-Type']}")

# JSON-Antwort verarbeiten
if response.status_code == 200:
    daten = response.json()
    print(f"API: {daten['current_user_url']}")
else:
    print(" Fehler beim Abrufen")
Ausgabe
Status: 200 Content-Type: application/json API: https://api.github.com/user
Python vs. JavaScript — Das kennst du schon!

Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:

Python
import requests
r = requests.get(url)
daten = r.json()
JavaScript
fetch(url)
  .then(r => r.json())
  .then(daten => console.log(daten));
Merke: Python: requests.get() is synchronous and simple. JavaScript: fetch() is asynchronous and returns Promises. Both fetch data from the server.

Processing JSON Responses

Most modern APIs deliver JSON. With response.json() Python converts the response directly into a dictionary — then you can access the data as usual.

Python
import requests

# Öffentliche API: Zufälliger Nutzer
url = "https://randomuser.me/api/"
response = requests.get(url)

if response.status_code == 200:
    daten = response.json()
    user = daten["results"][0]
    
    name = user["name"]["first"] + " " + user["name"]["last"]
    email = user["email"]
    land = user["location"]["country"]
    
    print(f"👤 Name: {name}")
    print(f"📧 E-Mail: {email}")
    print(f" Land: {land}")
else:
    print(f" Fehler: {response.status_code}")
Ausgabe
👤 Name: John Doe 📧 E-Mail: john.doe@example.com Land: Germany
Python vs. JavaScript — Das kennst du schon!

Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:

Python
daten = response.json()
user = daten['results'][0]
print(user['name']['first'])
JavaScript
const daten = await response.json();
const user = daten.results[0];
console.log(user.name.first);
Merke: Accessing nested JSON data is almost identical in Python and JavaScript — only the syntax for keys differs slightly.

Using API Keys Safely

Many APIs require an API key — a password for API access. Never store keys directly in code! Use environment variables instead.

Security Warning

If you commit API keys to GitHub, they can be read and abused by bots. Always use os.getenv()!

Python
import os

# API-Key aus Umgebungsvariable holen
api_key = os.getenv("OPENWEATHER_API_KEY")

if not api_key:
    print("  Kein API-Key gefunden! Setze die Umgebungsvariable:")
    print("   export OPENWEATHER_API_KEY=dein_key")
else:
    print(" API-Key geladen.")
    # Sicher verwenden
    url = f"https://api.openweathermap.org/data/2.5/weather?q=Wien&appid={api_key}"
    # ... Request senden
Ausgabe
Kein API-Key gefunden! Setze die Umgebungsvariable: export OPENWEATHER_API_KEY=dein_key

Error Handling with APIs

Network requests can fail for many reasons: No internet, server overloaded, wrong URL. Good error handling makes your program robust.

Python
import requests

def hole_daten(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()  # Löst Exception bei 4xx/5xx aus
        return response.json()
    except requests.exceptions.Timeout:
        print("  Zeitüberschreitung — Server antwortet nicht.")
    except requests.exceptions.ConnectionError:
        print(" Keine Internetverbindung.")
    except requests.exceptions.HTTPError as e:
        print(f" HTTP-Fehler: {e}")
    except requests.exceptions.RequestException:
        print(" Unbekannter Netzwerkfehler.")
    return None

# Test
daten = hole_daten("https://httpbin.org/status/404")
if daten:
    print("Daten erfolgreich geladen.")
Ausgabe
HTTP-Fehler: 404 Client Error: NOT FOUND for url: ...

APIs in Action: Fetching Weather

Now everything comes together: We fetch real weather data — without an API key, thanks to the public wttr.in API.

Python
import requests

def wetter_abrufen(stadt):
    url = f"https://wttr.in/{stadt}?format=%C+%t&lang=de"
    try:
        response = requests.get(url, timeout=5)
        if response.status_code == 200:
            return response.text.strip()
        return " Stadt nicht gefunden"
    except requests.exceptions.RequestException:
        return " Netzwerkfehler"

# Nutzung
stadt = input(" Für welche Stadt willst du das Wetter wissen? ")
wetter = wetter_abrufen(stadt)
print(f"\n🌤️  Wetter in {stadt}: {wetter}")
Ausgabe
Für welche Stadt willst du das Wetter wissen? Wien 🌤️ Wetter in Wien: Partly cloudy +18°C

Warm-Up: Fetch Bitcoin Price

Use the CoinDesk API to fetch the current Bitcoin price in Euros and display it.

Hinweis: import requests url = 'https://api.coindesk.com/v1/bpi/currentprice.json' try: r = requests.get(url, timeout=5) daten = r.json() preis = daten['bpi']['EUR']['rate'] print(f'💰 Bitcoin-Preis: {preis} €') except Exception as e: print(f' Fehler: {e}')

Solution
import requests

url = 'https://api.coindesk.com/v1/bpi/currentprice.json'
try:
    r = requests.get(url, timeout=5)
    daten = r.json()
    preis = daten['bpi']['EUR']['rate']
    print(f'💰 Bitcoin-Preis: {preis} €')
except Exception as e:
    print(f' Fehler: {e}')

Challenge: GitHub Profile Info

Create a program that fetches public GitHub profile information. The user enters a username, the program shows followers and public repos.

Hinweis: import requests user = input('GitHub Username: ') url = f'https://api.github.com/users/{user}' try: r = requests.get(url, timeout=5) if r.status_code == 200: d = r.json() print(f"👤 {d['name'] or d['login']}") print(f" Öffentliche Repos: {d['public_repos']}") print(f"👥 Follower: {d['followers']}") else: print(' Benutzer nicht gefunden') except requests.exceptions.RequestException: print(' Netzwerkfehler')

Solution
import requests

user = input('GitHub Username: ')
url = f'https://api.github.com/users/{user}'
try:
    r = requests.get(url, timeout=5)
    if r.status_code == 200:
        d = r.json()
        print(f"👤 {d['name'] or d['login']}")
        print(f" Öffentliche Repos: {d['public_repos']}")
        print(f"👥 Follower: {d['followers']}")
    else:
        print(' Benutzer nicht gefunden')
except requests.exceptions.RequestException:
    print(' Netzwerkfehler')

PyBuddy-Checkpoint: Weather Function

PyBuddy gets a wetter() function that fetches and displays the current weather for a city.

Hinweis: # pybuddy/main.py import requests def wetter(stadt): url = f'https://wttr.in/{stadt}?format=%C+%t&lang=de' try: r = requests.get(url, timeout=5) return r.text.strip() if r.status_code == 200 else 'Nicht gefunden' except: return 'Netzwerkfehler' stadt = input(' Stadt: ') print(f'🌤️ {wetter(stadt)}')

Solution
# pybuddy/main.py
import requests

def wetter(stadt):
    url = f'https://wttr.in/{stadt}?format=%C+%t&lang=de'
    try:
        r = requests.get(url, timeout=5)
        return r.text.strip() if r.status_code == 200 else 'Nicht gefunden'
    except:
        return 'Netzwerkfehler'

stadt = input(' Stadt: ')
print(f'🌤️  {wetter(stadt)}')
Didactic Break

In Fortnite the game constantly calls APIs: Weather data for events, shop content, matchmaking information. Every skin purchase, every friend request, every victory — everything goes via HTTP requests to Epic's servers. You are building the same technology!

Zusammenfassung

  • requests.get() → fetch data from APIs
  • response.json() → convert JSON to dictionary
  • Always store API keys in environment variables
  • try/except for robust network requests
  • Real APIs make your programs come alive