.. include:: markup.rst ***************** Ein- und Ausgaben ***************** In diesem Kapitel widmen wir uns der Frage: Wie kommuniziere ich mit der Software? Anders gesagt: Wie werden :mark:`Daten übergeben bzw. ausgegeben`? Bildschirmausgaben ================== Text auf dem Bildschirm kann mit Hilfe des Schlüsselwortes ``print`` ausgegeben werden. Etwa so: :: In [1]: print("Ein Text", " aus zwei Teilen.") Ein Text aus zwei Teilen. In [2]: dict = {34 : "Susi", 45 : "Walter"} In [3]: print(dict) {34: 'Susi', 45: 'Walter'} In [4]: h=13; m=37 In [5]: print(f"Es ist {h}:{m} Uhr.") Es ist 13:37 Uhr. Betrachtet man die ``print`` Funktion genauer, ist diese wie folgt definiert: .. code-block:: python print(value1, value2, ..., sep=' ', end='\n', file=sys.stdout, flush=False) d.h. per default wird ein Datenstrom erzeught welcher: * ein Leerzeichen zwischen ``value1``, ``value2`` und weiteren Werten ausgibt (beliebig viele Werte möglich), * nachdem alles ausgegeben wurde, wird ein Zeilenvorschub ``\n`` geschrieben, * die Ausgabe erfolgt am Bildschirm (``sys.stdout``) und * der Datenstrom wird gepuffert d.h. nicht gleich ausgegeben (``flush`` Befehl). Die Ausgabe der ``print`` Funktion kann auch in ein :mark:`File` umgeleitet werden (genaueres siehe später). Tastatureingaben ================ Bei dem Zahlenratebeispiel von vorher haben wir bereits folgenden Befehl verwendet um :mark:`vom Bildschirm zu lesen`: :: In [1]: guess = input("Raten Sie: ") Raten Sie: 4 Der :mark:`Programmlauf stoppt` so lange, bis Zeichen über die Tastatur eingegeben und mit ``ENTER`` bestätigt werden. Wichtig dabei zu erwähnen dass die Daten als Zeichenkette eingelesen werden. :: In [2]: print(guess, type(guess)) 4 .. hint:: Diese Art der Eingabe wird derzeit bei Programmen kaum verwendet da grafische Oberfläche diese Aufgabe übernehmen. Dateien ======= Wichtiger als die Bildschirm Ein- und Ausgabe ist das :mark:`Lesen und Schreiben von Daten aus Dateien`. Dadurch wird eine Dokumentation gewährleistet. Daten aus einer Datei auslesen ------------------------------ Beispiel: Ausgangspunkt ist eine bestehende Datei z.B. ``woerterbuch.txt`` im ``src/`` mit folgenden Inhalt: :: Spain Spanien Germany Deutschland Sweden Schweden France Frankreich Italy Italien .. hint:: Dieses File können Sie auch mit einem Editor erzeugen. Sofern Sie die IPython-Konsole für dieses Beispiel verwenden wollen, wechseln Sie in das Verzeichnis wo sich dieses File befindet z.B. mit ``cd C:/Users/.../GdP/src``. Hier wird das Skript ``ea_woerterbuch.py`` verwendet. Im ersten Schritt wird ein :mark:`Fileobjekt` (:mark:`output stream`) durch den Befehl ``open`` erzeugt: :: fobj = open("woerterbuch.txt", "r") Mit der Option ``"r"`` wird das File nur zum Lesen (:mark:`read`) geöffnet. Danach kann man z.B. Zeile für Zeile mit einer ``for``-Schleife in ein Dictionary einlesen: :: woerter = {} for line in fobj: line = line.strip() zuordnung = line.split(" ") woerter[zuordnung[0]] = zuordnung[1] Erklärungen: * Die ``strip``-Methode des Strings entfernt dabei alle Whitespace-Zeichen (Zeilenumbrüche, etc). * Die ``split``-Methode erzeugt eine Liste mit 2 Einträgen. Nach dem Lesen muss das :mark:`Fileobjekt geschlossen` werden mit: :: fobj.close() Das gesamte Programm lautet mit einer Ausgabe (``ea_woerterbuch.py``): .. literalinclude:: src/ea_woerterbuch.py Um sich ein explizites Schließen zu ersparen, kann man auch ein ``with`` :mark:`Statement` verwenden (siehe ``ea_woerterbuch_with.py``): .. literalinclude:: src/ea_woerterbuch_with.py .. _Daten in eine Datei schreiben : Daten in eine Datei schreiben ----------------------------- Dies funktioniert im Wesentlichen ähnlich wie das Lesen. Hier ein Beispielcode: .. code-block:: python with open("ausgabe.txt", "w") as fobj2: #1 for engl in woerter: print(engl, woerter[engl], sep=":", file=fobj2) #2 Erklärungen: * In Zeile ``#1`` wird ein Fileobjekt zum Schreiben (:mark:`write`) mit ``"w"`` geöffnet. * In Zeile ``#2`` wird dann dieses Objekt mit der ``print`` Funktion von oben zum Schreiben verwendet. Der Separator ist dabei ein ``:``. * Die Ausgabe im File lautet dabei: :: Spain:Spanien Germany:Deutschland Sweden:Schweden France:Frankreich Italy:Italien .. hint:: * Mit der Option ``w`` öffnet man ein File und löscht den Inhalt. * Möchte man Daten an ein bestehendes File anhängen, verwendet man ``a`` (:mark:`append`) statt ``w``. * Sollen Binärfiles geschrieben werden, kann man z.B. ``wb`` verwenden (:mark:`write binary`) Hier noch ein umfangreicheres Beispiel mit einigen :mark:`"Tricks"` (``ea_file_stdout.py``): .. literalinclude:: src/ea_file_stdout.py :language: python Anmerkungen: * Es wird ein generisches ``outstream`` Objekt definiert (Typ unklar, daher vorab ``None``). * Die Eingabeabfrage ändert alle Zeichen auf ``upper``. Daher arbeitet das Skript mit Groß- und Kleinbuchstaben. * Wir setzen den ``outstream`` entsprechend d.h. Bildschirm oder Textfile Ausgabe. * Zusätzlich gibt es ein ``else`` für den Fall dass nichts eingegeben wurde. * Die ``None`` Definition am Anfang plus ``if`` Abfrage am Ende vermeiden Programmabstürze. * Durch die Angabe von mehreren Werten in der ``print`` Funktion, kann man einfach lange Zeilen lesbarer machen. Übungsbeispiele ==================== **Aufgabe 7.1** Holen Sie vom Verzeichnis ``src`` die Datei ``HU_land_hauptstadt.txt``. Diese Datei enthält eine Liste von Länder und deren Hauptstädte. 1) Schreiben Sie eine Funktion ``lesen()`` um diese Datei zu lesen und die Information in ein Dictionary zu speichern. Verwenden Sie das Land als Schlüssel und die Haupstadt als Wert. 2) Schreiben Sie eine Funktion ``zeige_Land()``, die für alle Länder diese Information im Format 'Hauptstadt von ..... ist .....' anzeigt. 3) Schreiben Sie eine Funktion ``neues_Land()``, die vom Benutzer einen Namen eines Landes und dessen Hauptstadt bekommt, und in Ihre interne Datenstruktur einfügt. Verwenden Sie dafür die Benutzereingabe über die Konsole (Befehl ``input``). Diese Funktion darf keine existierenden Informationen überschreiben. 4) Letzlich Schreiben Sie eine Funktion ``schreiben()``, die die vorhandene Information im ursprünglichen Format mit einem neuen Dateiname abspeichert. 5) Testen Sie das Programm mittels Hauptprogrammteil im selben Skript. .. note:: ``src`` bezieht sich auf https://ilsb.git-pages.tuwien.ac.at/nbm/gdp2022/src/ weitere Übungsbeispiele ==================== **Aufgabe 7.2** Erweitern Sie Aufgabe 7.1 wie folgt: 1) Schreiben Sie eine Funktion ``entferne_Land()``, die vom Benutzer den Namen eines Landes bekommt (wieder mittels ``input``), und den entsprechenden Eintrag aus dem Dictionary löscht. 2) Testen Sie das Programm mittels Hauptprogrammteil im selben Skript.