Benutzer-Werkzeuge

Webseiten-Werkzeuge


projekt:python_erste_skripte

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
projekt:python_erste_skripte [2026/02/15 14:55] torsten.roehlprojekt: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) sowie einer Python-Umgebung eine professionelle Arbeitsweise möglich wird. Nach dem Durcharbeiten dieser Seite kann mit den eigentlichen Projekten begonnen werden.//+//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)  eine professionelle Arbeitsweise möglich wird. Nach dem Durcharbeiten dieser Seite kann mit den eigentlichen Projekten begonnen werden.//
  
-  * 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 - "Schnell, schneller, am schnellsten"** **Aufgabe - "Schnell, schneller, am schnellsten"**
  
-Schreibe ein Python-Programm (''reflexio''), das Reaktionszeiten messen kann.+Schreibe ein Python-Programm (''reflex_simple.py''), das Reaktionszeiten messen kann.
  
   * Beim Start soll eine kleine Anleitung erscheinen.   * Beim Start soll eine kleine Anleitung erscheinen.
Zeile 35: Zeile 34:
 </WRAP> </WRAP>
  
-==== Quellcode ==== +===== Quellcode ===== 
-<code python reflexio.py>+<code python reflex_simple.py>
 #!/usr/bin/env python3 #!/usr/bin/env python3
  
Zeile 42: Zeile 41:
 # @author: DEIN NAME # @author: DEIN NAME
 # @version: 1.0 # @version: 1.0
-# @usage:    ./reflexio.py+# @usage:    ./reflex_simple.py
    
    
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("==============  ANLEITUNG ===============================-")+    print("==============  ANLEITUNG ================================")
     print("(1) Drücke 'ENTER', um die Messung zu starten.")     print("(1) Drücke 'ENTER', um die Messung zu starten.")
     print("(2) Drücke 'ENTER', sobald  die Meldung 'JETZT' erscheint!")     print("(2) Drücke 'ENTER', sobald  die Meldung 'JETZT' erscheint!")
Zeile 82: Zeile 81:
 </code> </code>
  
-==== 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: ''#!/usr/bin/env python3''   - Erste Zeile (**Shebang**) in die Datei einfügen: ''#!/usr/bin/env python3''
-  - Datei ausführbar machen: ''chmod +x reflexio'' +  - Datei ausführbar machen: ''chmod +x reflex_simple.py'' 
-  - Starten: .''/reflexio''+  - Starten: .''/reflex_simple.py''
  
  
  
-===== Example 1reflexio-advanced  =====+====== Example 2reflex_advanced.py  =====
  
 <WRAP center round box 90%> <WRAP center round box 90%>
-Aufgabe – „Schnell, schneller, am schnellsten“+**Aufgabe – „Schnell, schneller, am schnellsten“**
  
-Schreibe ein Python-Programm (''reflexio-advanced''), das Reaktionszeiten misst, diese optional sammelt und in einer gemeinsamen Datei speichert. Auf diese Weise soll beispielsweise der Mittelwert vieler einzelner Messungen berechnet werden können.+Schreibe ein Python-Programm (''reflex_advanced.py''), das Reaktionszeiten misst, diese sammelt und in einer gemeinsamen Datei speichert. Auf diese Weise soll beispielsweise der Mittelwert vieler einzelner Messungen berechnet werden können.
  
-  * Beim Start soll eine kleine Anleitung erscheinen. +  * Beim Programmstart sollen folgende Optionen ausgewählt werden können: 
-      * Der User kann zwischen Einzelmessung, Mittelwert anzeigen oder Reset wählen. +      * 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).+
  
-</WRAP>+  * **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:** Anzeige der Anzahl gespeicherter Messwerte sowie des aktuellen Durchschnitts.
 +      * Alle Messungen sollen in einer gemeinsamen Datei gespeichert werden.
  
-====  Environment anlegen ==== +  * **Reset:** Der User soll die Möglichkeit haben, alle gespeicherten Messwerte zurückzusetzen (Reset der Datei).
-<WRAP center round box 80%> +
-**AufgabeAnlegen einer Python-Environment**+
  
-Lege eine Umgebung +  **Hilfe:** Anzeige einer kurzen Anleitung zur Bedienung des Programms.
-  ''~/devel/projects/refexio_advanced/refexio_advanced_env'' an.  +
-Hierfür muss der Ordner ''~/devel/projects/refexio_advanced'' bereits vorhanden sein.+
  
 </WRAP> </WRAP>
  
-<note tip> 
-Das Anlegen und Managen einer Umgebung ist hier 
-[[python_python-umgebung_env_einrichten_vorbereitungen_fuer_projekte_schaffen|Python ENV]] 
-ausführlich beschrieben. 
-</note> 
  
-Wechsle anschließend in die Umgebung, um das Example zu bearbeiten! 
  
-====  Programmstruktur anlegen  ====+=====  Programmstruktur anlegen  =====
  
-=== Hauptverzeichnis des Projekts: reflexio-advancded ===+==== Hauptverzeichnis des Projekts: course_reflex_advanced ====
 <code bash> <code bash>
-pi@raspi88:~/devel/projects/reflexio_advanced $ pwd +pi@raspi88:~/devel/projects/course_reflex_advanced $ pwd 
-/home/pi/devel/projects/reflexio_advanced+/home/pi/devel/projects/course_reflex_advanced
 </code> </code>
-=== Programmstrukur ===+==== Programmstruktur ====
  
 <code bash> <code bash>
-└── reflexio_advanced             python3 -m venv reflexio_advanced_env +└── course_reflex_advanced        Projektverzeichnis 
-    ├── reflexio_advanced_env +    │   
-    │   └── ... +    ── data                      # Ordner für die Messwerte (messwerte.txt)    
-    ── data                      # Ordner für die Messwerte (messwerte.txt)    +
     └── src                       # Ordner für den Quellcode     └── src                       # Ordner für den Quellcode
         ├── core                  # core-Verzeichnis          ├── core                  # core-Verzeichnis 
         │   ├── __init__.py       # Erforderlich für Python!         │   ├── __init__.py       # Erforderlich für Python!
 +        │   ├── utility.py        # Hilfsfunktionen        
         │   └── logic.py          # Programm-Logik         │   └── logic.py          # Programm-Logik
-        └── reflexio_advanced.py  # Main Programm+        └── reflex_advanced.py  # Main Programm
 </code> </code>
  
Zeile 152: Zeile 145:
  
  
-====  Quellcode ====+=====  Quellcode =====
  
 +====  ohne Programmstruktur ====
 +
 +<note>
 +Der untenstehende Code funktioniert, wird im Folgenden jedoch modularisiert.
 +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.
 +
 +Der Code – insbesondere die Funktionen – sollen ebenfalls dokumentiert werden, was im Kurs gezeigt wird.
 +</note>
 +
 +
 +++++ ohne Programmstruktur |
 +
 +<code python   reflex_spaghetti.py>
 +#!/usr/bin/env python3
 +
 +import time
 +import random
 +import os
 +
 +VERSION = "This is reflex_spaghetti v1.0.0"
 +DATA_FILENAME = "messwerte.txt"
 +DATA_DIR = "data"
 +
 +
 +def main():
 +    print(VERSION)
 +
 +    # --- Beginn get_file() ---
 +    base_dir = os.path.dirname(__file__)
 +    data_path = os.path.join(base_dir, DATA_DIR)
 +    os.makedirs(data_path, exist_ok=True)
 +    file_path = os.path.join(data_path, DATA_FILENAME)
 +    # --- Ende get_file() ---
 +
 +    while True:
 +
 +        # --- Beginn show_menu() ---
 +        print("\n---------------------------------------------------------")
 +        print("m - Messen")
 +        print("s - Statistik anzeigen")
 +        print("r - Reset")
 +        print("h - Hilfe")
 +        print("x - Beenden")
 +        print("---------------------------------------------------------")
 +        # --- Ende show_menu() ---
 +
 +        choice = input("Eingabe: ").strip().lower()
 +
 +        # =====================================================
 +        # MESSEN
 +        # =====================================================
 +        if choice == "m":
 +
 +            # --- Beginn start_measurement() ---
 +            print("\nDrücke 'ENTER', um die Messung zu starten.")
 +            input()
 +            print("Status: Warte auf das Signal...\n")
 +
 +            time.sleep(random.uniform(2, 6))
 +
 +            print("JETZT!"        
 +
 +            start = time.perf_counter()
 +            input()
 +            end = time.perf_counter()
 +            reaction_time = end - start
 +            # --- Ende start_measurement() ---
 +
 +            print("Status: Messung beendet")
 +            print(f"Reaktionszeit: {reaction_time:.3f} Sekunden")
 +
 +            # --- Beginn save_value() ---
 +            with open(file_path, "a") as f:
 +                f.write(f"{reaction_time}\n")
 +            # --- Ende save_value() ---
 +
 +            # --- Beginn load_values() ---
 +            if os.path.exists(file_path):
 +                with open(file_path, "r") as f:
 +                    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"Anzahl Messwerte: {len(values)}")
 +                print(f"Durchschnitt: {avg:.3f} Sekunden")
 +            # --- Ende calculate_average() ---
 +
 +        # =====================================================
 +        # STATISTIK
 +        # =====================================================
 +        elif choice == "s":
 +
 +            # --- Beginn load_values() ---
 +            if os.path.exists(file_path):
 +                with open(file_path, "r") as f:
 +                    values = [float(line.strip()) for line in f if line.strip()]
 +            else:
 +                values = []
 +            # --- Ende load_values() ---
 +
 +            if not values:
 +                print("Es sind noch keine Messwerte vorhanden.")
 +            else:
 +                # --- Beginn calculate_average() ---
 +                avg = sum(values) / len(values)
 +                print(f"Anzahl Messwerte: {len(values)}")
 +                print(f"Durchschnitt: {avg:.3f} Sekunden")
 +                # --- Ende calculate_average() ---
 +
 +        # =====================================================
 +        # RESET
 +        # =====================================================
 +        elif choice == "r":
 +
 +            # --- Beginn reset_data() ---
 +            if os.path.exists(file_path):
 +                os.remove(file_path)
 +                print("Alle Messwerte wurden gelöscht.")
 +            else:
 +                print("Es sind keine gespeicherten Messwerte vorhanden.")
 +            # --- Ende reset_data() ---
 +
 +        # =====================================================
 +        # HILFE
 +        # =====================================================
 +        elif choice == "h":
 +
 +            # --- Beginn show_help() ---
 +            print("\n======================  ANLEITUNG  ======================")
 +            print("(1) Wähle 'm', um eine Messung zu starten.")
 +            print("(2) Drücke 'ENTER', um die Messung zu beginnen.")
 +            print("(3) Warte, bis die Meldung 'JETZT!' erscheint.")
 +            print("(4) Drücke sofort 'ENTER', um zu stoppen.")
 +            print("")
 +            print("s - Statistik anzeigen")
 +            print("r - Messwerte zurücksetzen")
 +            print("h - Diese Hilfe anzeigen")
 +            print("x - Programm beenden")
 +            print("=========================================================")
 +            # --- Ende show_help() ---
 +
 +        # =====================================================
 +        # BEENDEN
 +        # =====================================================
 +        elif choice == "x":
 +            print("\nProgramm beendet.")
 +            break
 +
 +        else:
 +            print("Ungültige Eingabe. Mit 'h' Hilfe anzeigen.")
 +
 +
 +if __name__ == "__main__":
 +    main()
 +
 +</code>
 +++++
 +
 +
 +====  mit Programmstruktur ====
 +
 +<note>
 +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“, also alles, was mit dem Messen und Speichern der Reaktionszeiten zu tun hat.
 +  * **Utility** Enthält Hilfsfunktionen, die nicht direkt zur Logik gehören, aber vom Programm benötigt werden.
 +  * **Hauptprogramm** Das eigentliche Programm. Hier sollte man starten, um die Funktionsweise des Programms zu überprüfen.
 +
 +</note>
 +
 +++++ mit Programmstruktur |
  
  
  
-=== Logik === 
-<code python> 
-# ========================================================= 
-# File: src/core/logic.py 
-# ========================================================= 
  
 +==== Logik ====
 +<code python logic.py >
 import time import time
 import random import random
Zeile 176: Zeile 351:
  
     print("JETZT!")     print("JETZT!")
-    print("Drücke jetzt sofort 'ENTER', um die Messung zu stoppen.") 
  
     start = time.perf_counter()     start = time.perf_counter()
Zeile 216: Zeile 390:
  
 </code> </code>
-=== Hauptprogramm === 
- 
-<code python> 
-#!/usr/bin/env python3 
  
 +==== utility ====
 +<code python utility.py>
 import os import os
-from core.logic import ( 
-    start_measurement, 
-    save_value, 
-    load_values, 
-    calculate_average, 
-    reset_data, 
-) 
- 
-VERSION = "This is reflexio-advanced v1.0" 
  
-BASE_DIR = os.path.dirname(os.path.dirname(__file__)) +
-DATA_DIR os.path.join(BASE_DIR, "data") +# VARIABLEN 
-FILE_PATH os.path.join(DATA_DIR, "messwerte.txt")+
 +DATADIR = "data" 
 +FILENAME = "messwerte.txt"
  
-os.makedirs(DATA_DIR, exist_ok=True)+
 +# FUNKTIONEN 
 +#
  
 +def get_file():
 +    base_dir = os.path.dirname(os.path.dirname(__file__))
 +    data_dir = os.path.join(base_dir, DATADIR)
 +    os.makedirs(data_dir, exist_ok=True)
 +    return os.path.join(data_dir, FILENAME)
  
 def show_help(): def show_help():
Zeile 262: Zeile 434:
     print("x - Beenden")     print("x - Beenden")
     print("---------------------------------------------------------")     print("---------------------------------------------------------")
 +</code>
  
 +
 +==== Hauptprogramm ====
 +
 +<code python reflex_advanced.py >
 +#!/usr/bin/env python3
 +
 +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)
 +
 +    file_path = get_file()
  
     while True:     while True:
Zeile 276: Zeile 467:
             print(f"Reaktionszeit: {reaction_time:.3f} Sekunden")             print(f"Reaktionszeit: {reaction_time:.3f} Sekunden")
  
-            save_value(FILE_PATH, reaction_time)+            save_value(file_path, reaction_time
 +            values = load_values(file_path)
  
-            values = load_values(FILE_PATH) 
             avg = calculate_average(values)             avg = calculate_average(values)
- 
             print(f"Anzahl Messwerte: {len(values)}")             print(f"Anzahl Messwerte: {len(values)}")
             print(f"Durchschnitt: {avg:.3f} Sekunden")             print(f"Durchschnitt: {avg:.3f} Sekunden")
  
         elif choice == "s":         elif choice == "s":
-            values = load_values(FILE_PATH+            values = load_values(file_path
-            avg = calculate_average(values) +             
- +            print() 
-            if avg is None:+            if not values:
                 print("Es sind noch keine Messwerte vorhanden.")                 print("Es sind noch keine Messwerte vorhanden.")
             else:             else:
 +                avg = calculate_average(values)
                 print(f"Anzahl Messwerte: {len(values)}")                 print(f"Anzahl Messwerte: {len(values)}")
                 print(f"Durchschnitt: {avg:.3f} Sekunden")                 print(f"Durchschnitt: {avg:.3f} Sekunden")
  
         elif choice == "r":         elif choice == "r":
-            if reset_data(FILE_PATH):+            print() 
 +            if reset_data(file_path):
                 print("Alle Messwerte wurden gelöscht.")                 print("Alle Messwerte wurden gelöscht.")
             else:             else:
Zeile 303: Zeile 495:
             show_help()             show_help()
  
-        elif choice == "x":+        elif choice == "x":           
             print("Programm beendet.")             print("Programm beendet.")
             break             break
Zeile 316: Zeile 508:
 </code> </code>
  
- +++++
- +
  
  
projekt/python_erste_skripte.1771167352.txt.gz · Zuletzt geändert: von torsten.roehl