Task_9: PoiType als StrEnum
This commit is contained in:
parent
0ba947861f
commit
24a7051632
52
TASK.md
52
TASK.md
@ -1,35 +1,41 @@
|
||||
# Task 8 — Python Package
|
||||
# Task 9 — PoiType als StrEnum
|
||||
|
||||
## Rückblick Task 7: Logging
|
||||
## Rückblick Task 8: Python Package
|
||||
|
||||
Ihr habt alle `print()`-Aufrufe durch das `logging`-Modul ersetzt. Warum ist das besser?
|
||||
Ihr habt das Projekt in ein Python-Package umgewandelt. Die wichtigsten Punkte:
|
||||
|
||||
- **Log-Level steuern ohne Code-Änderung:** Mit `logging.basicConfig(level=logging.DEBUG)`
|
||||
sieht man alle Details, mit `level=logging.WARNING` nur Probleme — ohne eine einzige
|
||||
Zeile im Anwendungscode anzufassen.
|
||||
- **`logger = logging.getLogger(__name__)`:** Jedes Modul bekommt seinen eigenen Logger,
|
||||
benannt nach dem Modul. Im Output sieht man sofort, *woher* eine Meldung kommt.
|
||||
- **`logging.basicConfig()` gehört in `main.py`** (den Einstiegspunkt), nicht in
|
||||
Hilfmodule — sonst konfiguriert jedes importierte Modul eigenständig das Logging,
|
||||
was zu unvorhersehbarem Verhalten führt.
|
||||
- **Alternative:** Für grössere Projekte lohnt sich eine separate Logging-Konfiguration
|
||||
via `logging.config.dictConfig()` oder eine externe Library wie `loguru`.
|
||||
- **Modul vs. Package:** Ein einzelnes `.py`-File ist ein Modul. Ein Ordner mit
|
||||
`__init__.py` ist ein Package — er kann mehrere Module bündeln und nach aussen
|
||||
eine saubere API exponieren.
|
||||
- **Relative Imports** (`from .models import POI`): Beziehen sich auf das eigene
|
||||
Package, sind refactoring-sicher und machen klar, dass etwas intern ist.
|
||||
Absolute Imports (`from overpass_project.models import POI`) funktionieren auch,
|
||||
sind aber abhängig vom Paketnamen.
|
||||
- **`from overpass import *`** ist problematisch, weil unklar ist, welche Namen
|
||||
importiert werden — das kann zu Namenskollisionen führen und erschwert das Lesen
|
||||
des Codes stark.
|
||||
|
||||
|
||||
## Aufgabe
|
||||
|
||||
Das Projekt besteht aktuell aus losen Modulen (`main.py`, `models.py`, `overpass.py`).
|
||||
Ziel ist es, daraus ein sauberes Python-Package zu machen.
|
||||
In `main.py` steht aktuell:
|
||||
|
||||
```python
|
||||
poi_type = "bergbahn"
|
||||
```
|
||||
|
||||
Das ist ein sogenannter **Magic String** — ein roher String, dem man nicht ansieht,
|
||||
welche Werte gültig sind, und der nirgends geprüft wird.
|
||||
|
||||
**Konkret:**
|
||||
|
||||
1. Lege eine leere `__init__.py` im Projektordner an.
|
||||
2. Benenne `overpass.py` in `fetcher.py` um (um später Namenskonflikte zu vermeiden).
|
||||
3. Passe alle Imports in `main.py` und `fetcher.py` auf **relative Imports** um
|
||||
(`from .models import …` statt `from models import …`).
|
||||
1. Füge in `models.py` eine `PoiType`-Klasse hinzu, die von `StrEnum` erbt,
|
||||
mit den Werten `BERGBAHN` und `RESTAURANT`.
|
||||
2. Ersetze in `main.py` den String `"bergbahn"` durch `PoiType.BERGBAHN`.
|
||||
3. Passe den Import in `main.py` entsprechend an.
|
||||
|
||||
**Fragen zum Nachdenken:**
|
||||
- Was ist der Unterschied zwischen einem Modul und einem Package in Python?
|
||||
- Was bewirkt `__init__.py` — was passiert ohne sie?
|
||||
- Wann verwendet man relative Imports, wann absolute?
|
||||
- Warum ist `from overpass import *` problematisch?
|
||||
- Was ist der Unterschied zwischen `Enum` und `StrEnum`?
|
||||
- Warum ist `PoiType.BERGBAHN` besser als der String `"bergbahn"`?
|
||||
- Was passiert, wenn jemand `PoiType("bergbahn")` schreibt — funktioniert das?
|
||||
- Wo könnte ein Enum an seine Grenzen stossen?
|
||||
@ -1,7 +1,6 @@
|
||||
import requests
|
||||
from pprint import pprint
|
||||
from models import POI
|
||||
import logging
|
||||
import requests
|
||||
from models import POI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -126,25 +125,4 @@ def _parse_pois(raw: dict, poi_type: str) -> list[POI]:
|
||||
pois.append(_parse_poi(data=element, poi_type=poi_type))
|
||||
except OverpassApiError as exc:
|
||||
logger.warning(f"POI übersprungen (id={element.get('id', '?')}): {exc}")
|
||||
return pois
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
BERGBAHN_QUERY = """
|
||||
[out:json][timeout:2][maxsize:500000];
|
||||
(
|
||||
node["aerialway"="station"]({bbox});
|
||||
way["aerialway"="station"]({bbox});
|
||||
node["railway"="funicular"]({bbox});
|
||||
way["railway"="funicular"]({bbox});
|
||||
node["railway"="station"]["funicular"="yes"]({bbox});
|
||||
);
|
||||
out center body;
|
||||
"""
|
||||
|
||||
bbox = (46.72, 9.70, 46.92, 10.00)
|
||||
# bbox = (45.8, 5.9, 47.8, 10.5)
|
||||
result = load_pois(overpass_query=BERGBAHN_QUERY, bbox=bbox)
|
||||
pprint(result)
|
||||
return pois
|
||||
@ -1,6 +1,6 @@
|
||||
import logging
|
||||
from overpass import load_pois, OverpassApiError
|
||||
from models import POI
|
||||
from .fetcher import load_pois, OverpassApiError
|
||||
from .models import POI
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user