7. Ein- und Ausgaben

In diesem Kapitel widmen wir uns der Frage: Wie kommuniziere ich mit der Software? Anders gesagt: Wie werden Daten übergeben bzw. ausgegeben?

7.1. 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:

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 File umgeleitet werden (genaueres siehe später).

7.2. Tastatureingaben

Bei dem Zahlenratebeispiel von vorher haben wir bereits folgenden Befehl verwendet um vom Bildschirm zu lesen:

In [1]: guess = input("Raten Sie: ")
Raten Sie: 4

Der 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 <class 'str'>

Hinweis

Diese Art der Eingabe wird derzeit bei Programmen kaum verwendet da grafische Oberfläche diese Aufgabe übernehmen.

7.3. Dateien

Wichtiger als die Bildschirm Ein- und Ausgabe ist das Lesen und Schreiben von Daten aus Dateien. Dadurch wird eine Dokumentation gewährleistet.

7.3.1. 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

Hinweis

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 Fileobjekt (output stream) durch den Befehl open erzeugt:

fobj = open("woerterbuch.txt", "r")

Mit der Option "r" wird das File nur zum Lesen (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 Fileobjekt geschlossen werden mit:

fobj.close()

Das gesamte Programm lautet mit einer Ausgabe (ea_woerterbuch.py):

woerter = {} 
fobj = open("woerterbuch.txt", "r") 
for line in fobj: 
    line = line.strip() 
    zuordnung = line.split(" ") 
    woerter[zuordnung[0]] = zuordnung[1] 
fobj.close()
print(woerter) 

Um sich ein explizites Schließen zu ersparen, kann man auch ein with Statement verwenden (siehe ea_woerterbuch_with.py):

woerter = {} 

with open("woerterbuch.txt", "r") as fobj: 
   for line in fobj: 
      line = line.strip() 
      zuordnung = line.split(" ") 
      woerter[zuordnung[0]] = zuordnung[1] 


print(woerter) 

7.3.2. Daten in eine Datei schreiben

Dies funktioniert im Wesentlichen ähnlich wie das Lesen. Hier ein Beispielcode:

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 (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
    

Hinweis

  • 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 (append) statt w.
  • Sollen Binärfiles geschrieben werden, kann man z.B. wb verwenden (write binary)

Hier noch ein umfangreicheres Beispiel mit einigen “Tricks” (ea_file_stdout.py):

""" In Diesem Beispiel geben wir einen String am Bildschirm 
    oder in ein File aus. """

# Import benoetigter Module
import sys
    
# Frage den Anwender was er will ... 
wahl = input("Ausgabe am (B)ilschirm / (F)ile : ")

# outstream Objekt  
outstream = None                                                

if (wahl.upper() == 'B') : 
     print(" ... Bildschirmausgabe")
     outstream = sys.stdout
elif (wahl.upper() == 'F') :
     print(" ... Fileausgabe")
     outstream = open("test.txt", "w") 
else : 
     print(f"FEHLER : Ausgabe '{wahl}' nicht implemtiert")

# Ausgabe sofern outstream nicht None
if outstream :           
    print("Das Fluchen ist die einzige Sprache,", 
          "die jeder Programmierer beherrscht.", 
          file=outstream)
    if not outstream == sys.stdout:
        outstream.close()

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.

7.4. Ü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.

7.5. 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.