projekt:python_erste_skripte
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| projekt:python_erste_skripte [2026/02/15 13:10] – [Quellcode] torsten.roehl | projekt:python_erste_skripte [2026/02/23 08:19] (aktuell) – [Example 2: reflex_advanced] torsten.roehl | ||
|---|---|---|---|
| Zeile 4: | Zeile 4: | ||
| [[python| ☚ zurück]] | [[python| ☚ zurück]] | ||
| - | //In diesem Abschnitt geht es darum zu lernen, wie man Python-Skripte erstellt und startet. Ausgehend von einem ersten einfachen Beispiel entwickeln wir im zweiten Beispiel das Programm weiter und zeigen, wie durch das Anlegen einer Projektstruktur (und von Modulen) | + | //In diesem Abschnitt geht es darum zu lernen, wie man Python-Skripte erstellt und startet. Ausgehend von einem ersten einfachen Beispiel entwickeln wir im zweiten Beispiel das Programm weiter und zeigen, wie durch das Anlegen einer Projektstruktur (und von Modulen) |
| - | * Einfache Python-Skripte | + | * Einfache Python-Skripte |
| - | * Anlegen und Nutzen einer **env** | + | |
| * Erstellen und Ausführen von Python-Skripten | * Erstellen und Ausführen von Python-Skripten | ||
| * Einbinden und Gebrauch von Modulen | * Einbinden und Gebrauch von Modulen | ||
| Zeile 21: | Zeile 20: | ||
| - | ===== Example 1: reflexio | + | ====== Example 1: reflex_simple.py |
| Zeile 27: | Zeile 26: | ||
| **Aufgabe - " | **Aufgabe - " | ||
| - | Schreibe ein Python-Programm ('' | + | Schreibe ein Python-Programm ('' |
| * Beim Start soll eine kleine Anleitung erscheinen. | * Beim Start soll eine kleine Anleitung erscheinen. | ||
| Zeile 35: | Zeile 34: | ||
| </ | </ | ||
| - | ==== Quellcode ==== | + | ===== Quellcode |
| - | <code python | + | <code python |
| # | # | ||
| Zeile 42: | Zeile 41: | ||
| # @author: DEIN NAME | # @author: DEIN NAME | ||
| # @version: 1.0 | # @version: 1.0 | ||
| - | # @usage: | + | # @usage: |
| Zeile 48: | Zeile 47: | ||
| import random | import random | ||
| - | VERSION = "This is reflexio v.1.0" | + | VERSION = "This is reflex_simple v1.0.0" |
| def main(): | def main(): | ||
| print(VERSION) | print(VERSION) | ||
| - | print(" | + | print(" |
| print(" | print(" | ||
| print(" | print(" | ||
| Zeile 82: | Zeile 81: | ||
| </ | </ | ||
| - | ==== Programm ausführen ==== | + | ===== Programm ausführen |
| - | Damit ein Python-Skript per './reflexio' ausführbar ist, müssen die unten aufgeführten Punkte erfüllt sein. | + | Damit ein Python-Skript per './reflex_simple.py' ausführbar ist, müssen die unten aufgeführten Punkte erfüllt sein. |
| - Erste Zeile (**Shebang**) in die Datei einfügen: ''# | - Erste Zeile (**Shebang**) in die Datei einfügen: ''# | ||
| - | - Datei ausführbar machen: '' | + | - Datei ausführbar machen: '' |
| - | - Starten: .''/ | + | - Starten: .''/ |
| - | ===== Example | + | ====== Example |
| <WRAP center round box 90%> | <WRAP center round box 90%> | ||
| - | Aufgabe – „Schnell, schneller, am schnellsten“ | + | **Aufgabe – „Schnell, schneller, am schnellsten“** |
| - | Schreibe ein Python-Programm ('' | + | Schreibe ein Python-Programm ('' |
| - | * Beim Start soll eine kleine Anleitung erscheinen. | + | * Beim Programmstart sollen folgende Optionen ausgewählt werden können: |
| - | * Der User kann zwischen Einzelmessung, | + | * Messen |
| - | * Anschließend soll der User möglichst schnell reagieren, um die Messung zu stoppen. | + | * Statistik |
| - | * Das Ergebnis der Einzelmessung soll auf der Kommandozeile sichtbar sein. | + | * Reset |
| - | * Zusätzlich soll – falls gewählt – der aktuelle Durchschnitt aller gespeicherten Messungen angezeigt werden. | + | * Hilfe |
| - | * Alle Messungen sollen in einer gemeinsamen Datei gespeichert werden (eine Datei für alle Werte). | + | * Beenden |
| - | * Der User soll die Möglichkeit haben, alle gespeicherten Messungen zurückzusetzen (Reset der Datei). | + | |
| - | </ | + | * **Messen:** Bei einer Einzelmessung soll der User möglichst schnell reagieren, um die Messung zu stoppen. |
| + | * Das Ergebnis der Einzelmessung soll auf der Kommandozeile sichtbar sein. | ||
| + | * Zusätzlich wird der aktuelle Durchschnitt aller gespeicherten Messungen angezeigt. | ||
| + | * **Statistik: | ||
| + | * Alle Messungen sollen in einer gemeinsamen Datei gespeichert werden. | ||
| - | ==== Environment anlegen ==== | + | |
| - | <WRAP center round box 80%> | + | |
| - | **Aufgabe: Anlegen einer Python-Environment** | + | |
| - | Lege eine Umgebung | + | |
| - | | + | |
| - | Hierfür muss der Ordner '' | + | |
| </ | </ | ||
| - | <note tip> | ||
| - | Das Anlegen und Managen einer Umgebung ist hier | ||
| - | [[python_python-umgebung_env_einrichten_vorbereitungen_fuer_projekte_schaffen|Python ENV]] | ||
| - | ausführlich beschrieben. | ||
| - | </ | ||
| - | Wechsle anschließend in die Umgebung, um das Example zu bearbeiten! | ||
| - | ==== Programmstruktur anlegen | + | ===== Programmstruktur anlegen |
| - | === Hauptverzeichnis des Projekts: | + | ==== Hauptverzeichnis des Projekts: |
| <code bash> | <code bash> | ||
| - | pi@raspi88: | + | pi@raspi88: |
| - | / | + | / |
| </ | </ | ||
| - | === Programmstrukur | + | ==== Programmstruktur ==== |
| <code bash> | <code bash> | ||
| - | └── | + | └── |
| - | ├── reflexio_advanced_env | + | │ |
| - | │ └── ... | + | |
| - | | + | |
| └── src # Ordner für den Quellcode | └── src # Ordner für den Quellcode | ||
| ├── core # core-Verzeichnis | ├── core # core-Verzeichnis | ||
| │ | │ | ||
| + | │ | ||
| │ | │ | ||
| - | └── | + | └── |
| </ | </ | ||
| Zeile 152: | Zeile 145: | ||
| - | ==== Quellcode ==== | + | ===== Quellcode |
| + | ==== ohne Programmstruktur ==== | ||
| + | < | ||
| + | Der untenstehende Code funktioniert, | ||
| + | Er ist alles andere als elegant – so etwas nennt man auch **Spaghetti-Code**. | ||
| + | Der Code ist | ||
| + | - sehr unübersichtlich und daher fehleranfällig, | ||
| + | - nicht gut wiederverwendbar, | ||
| + | - schwer zu debuggen, falls etwas nicht stimmt. | ||
| - | === Logik === | + | Der Code – insbesondere die Funktionen – sollen ebenfalls dokumentiert werden, was im Kurs gezeigt wird. |
| - | <code python> | + | </ |
| + | |||
| + | |||
| + | ++++ ohne Programmstruktur | | ||
| + | |||
| + | <code python | ||
| + | # | ||
| + | |||
| + | import time | ||
| + | import random | ||
| + | import os | ||
| + | |||
| + | VERSION | ||
| + | DATA_FILENAME | ||
| + | DATA_DIR | ||
| + | |||
| + | |||
| + | def main(): | ||
| + | print(VERSION) | ||
| + | |||
| + | # --- Beginn get_file() --- | ||
| + | base_dir = os.path.dirname(__file__) | ||
| + | data_path = os.path.join(base_dir, | ||
| + | os.makedirs(data_path, | ||
| + | file_path = os.path.join(data_path, | ||
| + | # --- Ende get_file() --- | ||
| + | |||
| + | while True: | ||
| + | |||
| + | # --- Beginn show_menu() --- | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | # --- Ende show_menu() --- | ||
| + | |||
| + | choice = input(" | ||
| + | |||
| + | # ===================================================== | ||
| + | # MESSEN | ||
| + | # ===================================================== | ||
| + | if choice == " | ||
| + | |||
| + | # --- Beginn start_measurement() --- | ||
| + | print(" | ||
| + | input() | ||
| + | print(" | ||
| + | |||
| + | time.sleep(random.uniform(2, | ||
| + | |||
| + | print(" | ||
| + | |||
| + | start = time.perf_counter() | ||
| + | input() | ||
| + | end = time.perf_counter() | ||
| + | reaction_time = end - start | ||
| + | # --- Ende start_measurement() --- | ||
| + | |||
| + | print(" | ||
| + | print(f" | ||
| + | |||
| + | # --- Beginn save_value() --- | ||
| + | with open(file_path, | ||
| + | f.write(f" | ||
| + | # --- Ende save_value() --- | ||
| + | |||
| + | # --- Beginn load_values() --- | ||
| + | if os.path.exists(file_path): | ||
| + | with open(file_path, | ||
| + | values = [float(line.strip()) for line in f if line.strip()] | ||
| + | else: | ||
| + | values = [] | ||
| + | # --- Ende load_values() --- | ||
| + | |||
| + | # --- Beginn calculate_average() --- | ||
| + | if values: | ||
| + | avg = sum(values) / len(values) | ||
| + | print(f" | ||
| + | print(f" | ||
| + | # --- Ende calculate_average() --- | ||
| + | |||
| + | # ===================================================== | ||
| + | # STATISTIK | ||
| + | # ===================================================== | ||
| + | elif choice == " | ||
| + | |||
| + | # --- Beginn load_values() --- | ||
| + | if os.path.exists(file_path): | ||
| + | with open(file_path, | ||
| + | values = [float(line.strip()) for line in f if line.strip()] | ||
| + | else: | ||
| + | values = [] | ||
| + | # --- Ende load_values() --- | ||
| + | |||
| + | if not values: | ||
| + | print(" | ||
| + | else: | ||
| + | # --- Beginn calculate_average() --- | ||
| + | avg = sum(values) / len(values) | ||
| + | print(f" | ||
| + | print(f" | ||
| + | # --- Ende calculate_average() --- | ||
| + | |||
| + | # ===================================================== | ||
| + | # RESET | ||
| + | # ===================================================== | ||
| + | elif choice == " | ||
| + | |||
| + | # --- Beginn reset_data() --- | ||
| + | if os.path.exists(file_path): | ||
| + | os.remove(file_path) | ||
| + | print(" | ||
| + | else: | ||
| + | print(" | ||
| + | # --- Ende reset_data() --- | ||
| + | |||
| + | # ===================================================== | ||
| + | # HILFE | ||
| + | # ===================================================== | ||
| + | elif choice == " | ||
| + | |||
| + | # --- Beginn show_help() --- | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print("" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | # --- Ende show_help() --- | ||
| + | |||
| + | # ===================================================== | ||
| + | # BEENDEN | ||
| + | # ===================================================== | ||
| + | elif choice == " | ||
| + | print(" | ||
| + | break | ||
| + | |||
| + | else: | ||
| + | print(" | ||
| + | |||
| + | |||
| + | if __name__ == " | ||
| + | main() | ||
| + | |||
| + | </ | ||
| + | ++++ | ||
| + | |||
| + | |||
| + | ==== mit Programmstruktur ==== | ||
| + | |||
| + | < | ||
| + | Der Code ist nun modularisiert. | ||
| + | Er ist deutlich übersichtlicher und lässt sich dadurch besser warten und verstehen. | ||
| + | |||
| + | Außerdem können z.B. die Module wiederverwendet werden – ebenso kann das Utility-Modul als Vorlage für andere Programme dienen. | ||
| + | |||
| + | Die Dokumentation der Methoden (Docstrings) fehlt hier übrigens noch. | ||
| + | |||
| + | * **Logik** Enthält die „Game-Logik“, | ||
| + | * **Utility** Enthält Hilfsfunktionen, | ||
| + | * **Hauptprogramm** Das eigentliche Programm. Hier sollte man starten, um die Funktionsweise des Programms zu überprüfen. | ||
| + | |||
| + | </ | ||
| + | |||
| + | ++++ mit Programmstruktur | | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Logik ==== | ||
| + | <code python | ||
| import time | import time | ||
| import random | import random | ||
| Zeile 164: | Zeile 343: | ||
| - | def messung_starten(): | + | def start_measurement(): |
| print(" | print(" | ||
| input() | input() | ||
| - | print(" | + | print(" |
| time.sleep(random.uniform(2, | time.sleep(random.uniform(2, | ||
| Zeile 175: | Zeile 354: | ||
| start = time.perf_counter() | start = time.perf_counter() | ||
| input() | input() | ||
| - | | + | |
| - | return | + | return |
| - | def wert_speichern(datei, wert): | + | def save_value(file_path, value): |
| - | with open(datei, " | + | with open(file_path, " |
| - | f.write(str(wert) + " | + | f.write(f"{value}\n") |
| - | def werte_laden(datei): | + | def load_values(file_path): |
| - | if not os.path.exists(datei): | + | if not os.path.exists(file_path): |
| return [] | return [] | ||
| - | | + | |
| - | with open(datei, " | + | with open(file_path, " |
| - | for zeile in f: | + | for line in f: |
| - | | + | |
| - | if zeile != "" | + | if line: |
| - | | + | |
| - | return | + | return |
| - | def mittelwert_berechnen(werte): | + | def calculate_average(values): |
| - | if len(werte) == 0: | + | if not values: |
| return None | return None | ||
| - | return sum(werte) / len(werte) | + | return sum(values) / len(values) |
| - | def datei_reset(datei): | + | def reset_data(file_path): |
| - | if os.path.exists(datei): | + | if os.path.exists(file_path): |
| - | os.remove(datei) | + | os.remove(file_path) |
| return True | return True | ||
| return False | return False | ||
| </ | </ | ||
| - | === Hauptprogramm === | ||
| - | <code python> | ||
| - | # | ||
| + | ==== utility ==== | ||
| + | <code python utility.py> | ||
| import os | import os | ||
| - | from core.logic import ( | ||
| - | messung_starten, | ||
| - | wert_speichern, | ||
| - | werte_laden, | ||
| - | mittelwert_berechnen, | ||
| - | datei_reset, | ||
| - | ) | ||
| - | VERSION | + | # |
| + | # VARIABLEN | ||
| + | # | ||
| + | DATADIR | ||
| + | FILENAME = " | ||
| - | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) | + | # |
| - | DATA_DIR = os.path.join(BASE_DIR, | + | # FUNKTIONEN |
| - | DATEI = os.path.join(DATA_DIR, | + | # |
| - | os.makedirs(DATA_DIR, exist_ok=True) | + | def get_file(): |
| + | base_dir = os.path.dirname(os.path.dirname(__file__)) | ||
| + | data_dir = os.path.join(base_dir, | ||
| + | | ||
| + | return os.path.join(data_dir, | ||
| - | + | def show_help(): | |
| - | def help(): | + | print(" |
| - | print(" | + | print(" |
| - | print(" | + | print(" |
| - | print(" | + | print(" |
| - | print(" | + | print(" |
| - | print(" | + | |
| - | print(" | + | |
| - | print("(2) Mittelwert anzeigen" | + | |
| - | print(" | + | |
| - | print(" | + | |
| - | print(" | + | |
| - | print("(3) Messungen zurücksetzen (Reset)" | + | |
| - | print(" | + | |
| print("" | print("" | ||
| - | print(" | + | print(" |
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| print(" | print(" | ||
| + | |||
| + | def show_menu(): | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Hauptprogramm ==== | ||
| + | |||
| + | <code python reflex_advanced.py > | ||
| + | # | ||
| + | |||
| + | from core.logic import ( | ||
| + | start_measurement, | ||
| + | save_value, | ||
| + | load_values, | ||
| + | calculate_average, | ||
| + | reset_data | ||
| + | ) | ||
| + | from core.utility import get_file, show_menu, show_help | ||
| + | |||
| + | VERSION = "This is reflex_advanced v1.0" | ||
| def main(): | def main(): | ||
| print(VERSION) | print(VERSION) | ||
| - | help() | ||
| - | | + | |
| - | wahl = input(" | + | |
| - | if wahl == " | + | while True: |
| - | | + | |
| - | print("Status: ...Messung beendet") | + | |
| - | print(f" | + | |
| - | + | ||
| - | wert_speichern(DATEI, reaktion) | + | |
| - | werte = werte_laden(DATEI) | + | if choice |
| - | | + | reaction_time = start_measurement() |
| + | | ||
| + | print(f" | ||
| - | | + | |
| - | | + | |
| - | elif wahl == " | + | avg = calculate_average(values) |
| - | | + | |
| - | | + | |
| - | | + | elif choice == " |
| - | print(" | + | values = load_values(file_path) |
| + | |||
| + | print() | ||
| + | | ||
| + | print(" | ||
| else: | else: | ||
| - | print(f" | + | |
| - | print(f" | + | |
| + | print(f" | ||
| - | elif wahl == "3": | + | elif choice |
| - | if datei_reset(DATEI): | + | print() |
| - | print(" | + | if reset_data(file_path): |
| + | print(" | ||
| else: | else: | ||
| - | print(" | + | print(" |
| - | elif wahl == "0": | + | elif choice |
| + | show_help() | ||
| + | |||
| + | elif choice == " | ||
| print(" | print(" | ||
| break | break | ||
| else: | else: | ||
| - | print(" | + | print(" |
| - | help() | + | |
| if __name__ == " | if __name__ == " | ||
| main() | main() | ||
| + | |||
| </ | </ | ||
| - | + | ++++ | |
| - | + | ||
projekt/python_erste_skripte.1771161026.txt.gz · Zuletzt geändert: von torsten.roehl
