"csv" --- CSV File Reading and Writing
**************************************

**Quellcode:** Lib/csv.py

======================================================================

Das sogenannte CSV-Format (Comma Separated Values) ist das gängigste
Import- und Exportformat für Tabellenkalkulationen und Datenbanken.
Das CSV-Format wurde bereits viele Jahre lang verwendet, bevor
versucht wurde, das Format in **RFC 4180** standardisiert zu
beschreiben. Das Fehlen eines klar definierten Standards führt dazu,
dass oft geringfügige Unterschiede in den Daten bestehen, die von
verschiedenen Anwendungen erzeugt und verarbeitet werden. Diese
Unterschiede können die Verarbeitung von CSV-Dateien aus verschiedenen
Quellen erschweren. Dennoch sind die Trennzeichen und
Anführungszeichen zwar unterschiedlich, das Gesamtformat ist jedoch
ähnlich genug, dass es möglich ist, ein einziges Modul zu schreiben,
das solche Daten effizient bearbeiten kann und dabei die Details des
Lesens und Schreibens der Daten vor dem Programmierer verbirgt.

The "csv" module implements classes to read and write tabular data in
CSV format.  It allows programmers to say, "write this data in the
format preferred by Excel," or "read data from this file which was
generated by Excel," without knowing the precise details of the CSV
format used by Excel.  Programmers can also describe the CSV formats
understood by other applications or define their own special-purpose
CSV formats.

The "csv" module's "reader" and "writer" objects read and write
sequences.  Programmers can also read and write data in dictionary
form using the "DictReader" and "DictWriter" classes.

Siehe auch:

  **PEP 305** - CSV-Datei-API
     Der Python Enhancement Proposal, in dem diese Erweiterung für
     Python vorgeschlagen wurde.


Modulinhalt
===========

The "csv" module defines the following functions:

csv.reader(csvfile, dialect='excel', **fmtparams)

   Gibt ein Leserobjekt zurück, das Zeilen aus der angegebenen
   *csvfile* verarbeitet. Eine *csvfile* muss eine iterierbare
   Sammlung von Zeichenketten sein, die jeweils dem vom Leser
   definierten CSV-Format entsprechen. Eine *csvfile* ist in der Regel
   ein dateiähnliches Objekt oder eine Liste. Wenn *csvfile* ein
   Dateiobjekt ist, sollte es mit "newline=''" geöffnet werden. [1]
   Ein optionaler *dialect*-Parameter kann angegeben werden, der dazu
   dient, eine Reihe von Parametern zu definieren, die für einen
   bestimmten CSV-Dialekt spezifisch sind. Er kann eine Instanz einer
   Unterklasse der Klasse "Dialect" oder einer der Zeichenketten sein,
   die von der Funktion "list_dialects()" zurückgegeben werden.  Die
   anderen optionalen Schlüsselwortargumente *fmtparams* können
   angegeben werden, um einzelne Formatierungsparameter im aktuellen
   Dialekt zu überschreiben.  Ausführliche Informationen zu den
   Dialekt- und Formatierungsparametern findest du im Abschnitt
   Dialekte und Formatierungsparameter.

   Each row read from the csv file is returned as a list of strings.
   No automatic data type conversion is performed unless the
   "QUOTE_NONNUMERIC" format option is specified (in which case
   unquoted fields are transformed into floats).

   Ein kurzes Anwendungsbeispiel:

      >>> import csv
      >>> with open('eggs.csv', newline='') as csvfile:
      ...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
      ...     for row in spamreader:
      ...         print(', '.join(row))
      Spam, Spam, Spam, Spam, Spam, Baked Beans
      Spam, Lovely Spam, Wonderful Spam

csv.writer(csvfile, dialect='excel', **fmtparams)

   Gibt ein Writer-Objekt zurück, das die Daten des Benutzers in durch
   Trennzeichen getrennte Zeichenketten für das angegebene
   dateiähnliche Objekt umwandelt. *csvfile* kann ein beliebiges
   Objekt mit einer "write()"-Methode sein. Wenn *csvfile* ein
   Dateiobjekt ist, sollte es mit "newline=''" geöffnet werden [1].
   Ein optionaler *dialect*-Parameter kann angegeben werden, der zur
   Definition eines Satzes von Parametern für einen bestimmten CSV-
   Dialekt verwendet wird. Es kann sich um eine Instanz einer
   Unterklasse der Klasse "Dialect" oder um eine der von der Funktion
   "list_dialects()" zurückgegebenen Zeichenketten handeln. Die
   anderen optionalen *fmtparams*-Schlüsselwortargumente können
   angegeben werden, um einzelne Formatierungsparameter im aktuellen
   Dialekt zu überschreiben. Vollständige Details zu Dialekten und
   Formatierungsparametern findest du im Abschnitt Dialekte und
   Formatierungsparameter. Um die Schnittstelle zu Modulen, die die
   DB-API implementieren, so einfach wie möglich zu gestalten, wird
   der Wert "None" als leere Zeichenkette geschrieben. Auch wenn dies
   keine umkehrbare Umwandlung ist, erleichtert es das Exportieren von
   SQL-NULL-Datenwerten in CSV-Dateien, ohne die von einem
   "cursor.fetch*"-Aufruf zurückgegebenen Daten vorher zu verarbeiten.
   Alle anderen Nicht-Zeichenketten-Daten werden vor dem Schreiben mit
   "str()" in Zeichenketten umgewandelt.

   Ein kurzes Anwendungsbeispiel:

      import csv
      with open('eggs.csv', 'w', newline='') as csvfile:
          spamwriter = csv.writer(csvfile, delimiter=' ',
                                  quotechar='|', quoting=csv.QUOTE_MINIMAL)
          spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
          spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

csv.register_dialect(name[, dialect[, **fmtparams]])

   Ordne *dialect* dem *name* zu. *name* muss eine Zeichenkette sein.
   Der Dialekt kann entweder durch die Übergabe einer Unterklasse von
   "Dialect" oder durch *fmtparams*-Schlüsselwortargumente oder beides
   angegeben werden, wobei Schlüsselwortargumente die Parameter des
   Dialekts überschreiben. Ausführliche Informationen zu Dialekten und
   Formatierungsparametern findest du im Abschnitt Dialekte und
   Formatierungsparameter.

csv.unregister_dialect(name)

   Löscht den mit *name* verknüpften Dialekt aus dem Dialektregister.
   Es wird eine Ausnahme vom Typ "Error" ausgelöst, wenn *name* kein
   registrierter Dialektname ist.

csv.get_dialect(name)

   Gibt den mit *name* verknüpften Dialekt zurück. Es wird ein Fehler
   vom Typ "Error" ausgelöst, wenn *name* kein registrierter
   Dialektname ist. Diese Funktion gibt ein unveränderliches "Dialect"
   zurück.

csv.list_dialects()

   Gibt die Namen aller registrierten Dialekte zurück.

csv.field_size_limit([new_limit])

   Gibt die aktuell vom Parser zugelassene maximale Feldgröße zurück.
   Wenn *new_limit* angegeben wird, wird dies zur neuen Obergrenze.

The "csv" module defines the following classes:

class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

   Erstelle ein Objekt, das wie ein gewöhnlicher Reader funktioniert,
   jedoch die Informationen in jeder Zeile einem "dict" zuordnet,
   dessen Schlüssel durch den optionalen Parameter *fieldnames*
   vorgegeben werden.

   The *fieldnames* parameter is a *sequence*.  If *fieldnames* is
   omitted, the values in the first row of file *f* will be used as
   the fieldnames.  Regardless of how the fieldnames are determined,
   the dictionary preserves their original ordering.

   Wenn eine Zeile mehr Felder enthält als Feldnamen vorhanden sind,
   werden die übrigen Daten in eine Liste aufgenommen und unter dem
   durch *restkey* angegebenen Feldnamen gespeichert (Standardwert ist
   "None"). Wenn eine nicht leere Zeile weniger Felder enthält als
   Feldnamen vorhanden sind, werden die fehlenden Werte mit dem Wert
   von *restval* aufgefüllt (Standardwert ist "None").

   Alle anderen optionalen Argumente oder Schlüsselwortargumente
   werden an die zugrunde liegende Instanz von "reader" übergeben.

   Geändert in Version 3.6: Die zurückgegebenen Zeilen haben nun den
   Typ "OrderedDict".

   Geändert in Version 3.8: Die zurückgegebenen Zeilen haben nun den
   Typ "dict".

   Ein kurzes Anwendungsbeispiel:

      >>> import csv
      >>> with open('names.csv', newline='') as csvfile:
      ...     reader = csv.DictReader(csvfile)
      ...     for row in reader:
      ...         print(row['first_name'], row['last_name'])
      ...
      Eric Idle
      John Cleese

      >>> print(row)
      {'first_name': 'John', 'last_name': 'Cleese'}

class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

   Erstelle ein Objekt, das wie ein gewöhnlicher Writer funktioniert,
   aber Dictionarys auf Ausgabezeilen abbildet.  Der Parameter
   *fieldnames* ist eine "Sequenz" aus Schlüsseln, die die Reihenfolge
   festlegen, in der die Werte des an die Methode "writerow()"
   übergebenen Dictionarys in die Datei *f* geschrieben werden. Der
   optionale Parameter *restval* gibt den Wert an, der geschrieben
   werden soll, wenn im Dictionary ein Schlüssel fehlt, der in
   *fieldnames* enthalten ist.  Wenn das an die Methode "writerow()"
   übergebene Dictionary einen Schlüssel enthält, der nicht in
   **fieldnames** zu finden ist, gibt der optionale Parameter
   **extrasaction** an, welche Aktion durchgeführt werden soll. Ist er
   auf den Standardwert "'raise'" gesetzt, wird eine "ValueError"
   ausgelöst. Ist er auf "'ignore'" gesetzt, werden zusätzliche Werte
   im Dictionary ignoriert. Alle anderen optionalen oder
   Schlüsselwortargumente werden an die zugrunde liegende Instanz von
   "writer" übergeben.

   Beachte, dass der Parameter *fieldnames* der Klasse "DictWriter" im
   Gegensatz zur Klasse "DictReader" nicht optional ist.

   Ein kurzes Anwendungsbeispiel:

      import csv

      with open('names.csv', 'w', newline='') as csvfile:
          fieldnames = ['first_name', 'last_name']
          writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

          writer.writeheader()
          writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
          writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
          writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

class csv.Dialect

   Die Klasse "Dialect" ist eine Containerklasse, deren Attribute
   Informationen darüber enthalten, wie mit doppelten
   Anführungszeichen, Leerzeichen, Trennzeichen usw. umgegangen werden
   soll. Da es keine strenge CSV-Spezifikation gibt, erzeugen
   verschiedene Anwendungen CSV-Daten, die sich geringfügig
   voneinander unterscheiden. Instanzen von "Dialect" legen fest, wie
   sich Instanzen von "reader" und "writer" verhalten.

   Alle verfügbaren "Dialect"-Namen werden von "list_dialects()"
   zurückgegeben und können über deren Initialisierungsfunktionen
   ("__init__") wie folgt in bestimmten "reader" und "writer"-Klassen
   registriert werden:

      import csv

      with open('students.csv', 'w', newline='') as csvfile:
          writer = csv.writer(csvfile, dialect='unix')

class csv.excel

   Die Klasse "excel" definiert die üblichen Eigenschaften einer von
   Excel erstellten CSV-Datei. Sie ist unter dem Dialektnamen
   "'excel'" registriert.

class csv.excel_tab

   Die Klasse "excel_tab" definiert die üblichen Eigenschaften einer
   von Excel erstellten, durch Tabulatoren getrennten Datei. Sie ist
   unter dem Dialektnamen "'excel-tab'" registriert.

class csv.unix_dialect

   Die Klasse "unix_dialect" definiert die üblichen Eigenschaften
   einer auf UNIX-Systemen erzeugten CSV-Datei, d. h. mit "'\n'" als
   Zeilenabschlusszeichen und Anführungszeichen um alle Felder. Sie
   ist unter dem Dialektnamen "'unix'" registriert.

   Neu in Version 3.2.

class csv.Sniffer

   Die Klasse "Sniffer" dient dazu, das Format einer CSV-Datei zu
   ermitteln.

   Die Klasse "Sniffer" stellt zwei Methoden bereit:

   sniff(sample, delimiters=None)

      Analysiere das angegebene *Beispiel* und gib eine Unterklasse
      von "Dialect" zurück, die die gefundenen Parameter
      widerspiegelt. Wenn der optionale Parameter *delimiters*
      angegeben wird, wird er als Zeichenkette interpretiert, die
      mögliche gültige Trennzeichen enthält.

   has_header(sample)

      Analysiert den Beispieltext (von dem angenommen wird, dass er im
      CSV-Format vorliegt) und gibt "True" zurück, wenn die erste
      Zeile offenbar aus einer Reihe von Spaltenüberschriften besteht.
      Bei der Prüfung jeder Spalte wird eines von zwei zentralen
      Kriterien herangezogen, um abzuschätzen, ob das Beispiel eine
      Kopfzeile enthält:

      * Die zweite bis zur n-ten Zeile enthalten numerische Werte

      * Die zweite bis zur n-ten Zeile enthalten Zeichenfolgen, bei
        denen sich die Länge mindestens eines Werts von der des
        vermeintlichen Kopfes dieser Spalte unterscheidet.

      Twenty rows after the first row are sampled; if more than half
      of columns + rows meet the criteria, "True" is returned.

   Bemerkung:

     Diese Methode ist eine grobe Heuristik und kann sowohl zu falsch-
     positiven als auch zu falsch-negativen Ergebnissen führen.

Ein Beispiel für die Verwendung von "Sniffer":

   with open('example.csv', newline='') as csvfile:
       dialect = csv.Sniffer().sniff(csvfile.read(1024))
       csvfile.seek(0)
       reader = csv.reader(csvfile, dialect)
       # ... process CSV file contents here ...

The "csv" module defines the following constants:

csv.QUOTE_ALL

   Weist Objekte von "writer" an, alle Felder in Anführungszeichen zu
   setzen.

csv.QUOTE_MINIMAL

   Instructs "writer" objects to only quote those fields which contain
   special characters such as *delimiter*, *quotechar* or any of the
   characters in *lineterminator*.

csv.QUOTE_NONNUMERIC

   Weist Objekte von "writer"  an, alle nicht-numerischen Felder in
   Anführungszeichen zu setzen.

   Instructs the reader to convert all non-quoted fields to type
   *float*.

csv.QUOTE_NONE

   Instructs "writer" objects to never quote fields.  When the current
   *delimiter* occurs in output data it is preceded by the current
   *escapechar* character.  If *escapechar* is not set, the writer
   will raise "Error" if any characters that require escaping are
   encountered.

   Instructs "reader" to perform no special processing of quote
   characters.

The "csv" module defines the following exception:

exception csv.Error

   Wird von einer der Funktionen ausgelöst, wenn ein Fehler erkannt
   wird.


Dialekte und Formatierungsparameter
===================================

Um die Angabe des Formats von Eingabe- und Ausgabesätzen zu
vereinfachen, werden bestimmte Formatierungsparameter zu Dialekten
zusammengefasst. Ein Dialekt ist eine Unterklasse der Klasse
"Dialect", die verschiedene Attribute enthält, welche das Format der
CSV-Datei beschreiben. Beim Erstellen von Objekten vom Typ "reader"
oder "writer" kann der Programmierer eine Zeichenkette oder eine
Unterklasse der Klasse "Dialect" als Dialektparameter angeben.
Zusätzlich zum oder anstelle des Parameters *dialect* kann der
Programmierer auch einzelne Formatierungsparameter angeben, die
dieselben Namen tragen wie die unten für die Klasse "Dialect"
definierten Attribute.

Dialekte unterstützen die folgenden Attribute:

Dialect.delimiter

   Eine Zeichenkette mit einem Zeichen, die zur Trennung von Feldern
   verwendet wird. Der Standardwert lautet „ "','" “.

Dialect.doublequote

   Legt fest, wie Instanzen von *quotechar*, die innerhalb eines
   Feldes vorkommen, selbst in Anführungszeichen gesetzt werden
   sollen. Bei der Einstellung "True" wird das Zeichen verdoppelt. Bei
   der Einstellung "False" wird das *escapechar* als Präfix vor dem
   *quotechar* verwendet. Die Standardeinstellung ist "True".

   Bei der Ausgabe wird, wenn *doublequote* auf "False" gesetzt ist
   und kein *escapechar* festgelegt wurde, ein "Error" ausgelöst,
   sobald ein *quotechar* in einem Feld gefunden wird.

Dialect.escapechar

   A one-character string used by the writer to escape the *delimiter*
   if *quoting* is set to "QUOTE_NONE" and the *quotechar* if
   *doublequote* is "False". On reading, the *escapechar* removes any
   special meaning from the following character. It defaults to
   "None", which disables escaping.

   Geändert in Version 3.11: Ein leeres *escapechar* ist nicht
   zulässig.

Dialect.lineterminator

   Die Zeichenkette, mit der die von "writer" erzeugten Zeilen
   abgeschlossen werden. Standardmäßig ist dies "'\r\n'".

   Bemerkung:

     Die Funktion "reader" ist fest so programmiert, dass sie entweder
     "'\r'" oder "'\n'" als Zeilenende erkennt und *lineterminator*
     ignoriert. Dieses Verhalten kann sich in Zukunft ändern.

Dialect.quotechar

   A one-character string used to quote fields containing special
   characters, such as the *delimiter* or *quotechar*, or which
   contain new-line characters.  It defaults to "'"'".

   Geändert in Version 3.11: Ein leeres *quotechar* ist nicht
   zulässig.

Dialect.quoting

   Controls when quotes should be generated by the writer and
   recognised by the reader.  It can take on any of the QUOTE_*
   constants and defaults to "QUOTE_MINIMAL".

Dialect.skipinitialspace

   When "True", spaces immediately following the *delimiter* are
   ignored. The default is "False".

Dialect.strict

   Wenn "True" gesetzt ist, wird bei fehlerhaften CSV-Eingaben die
   Ausnahme "Error" ausgelöst. Die Standardeinstellung ist "False".


Reader-Objekte
==============

Reader-Objekte ("DictReader"-Instanzen und Objekte, die von der
Funktion "reader()" zurückgegeben werden) haben die folgenden
öffentlichen Methoden:

csvreader.__next__()

   Gibt die nächste Zeile des iterierbaren Objekts des Readers als
   Liste (falls das Objekt von "reader()" zurückgegeben wurde) oder
   als Dictionary (falls es sich um eine Instanz von "DictReader"
   handelt) zurück, geparst gemäß dem aktuellen "Dialect".
   Normalerweise rufst du dies als "next(reader)" auf.

Reader-Objekte verfügen über die folgenden öffentlichen Attribute:

csvreader.dialect

   Eine schreibgeschützte Beschreibung des vom Parser verwendeten
   Dialekts.

csvreader.line_num

   Die Anzahl der Zeilen, die aus dem Quell-Iterator gelesen wurden.
   Dies ist nicht mit der Anzahl der zurückgegebenen Datensätze
   identisch, da Datensätze sich über mehrere Zeilen erstrecken
   können.

DictReader-Objekte verfügen über das folgende öffentliche Attribut:

DictReader.fieldnames

   Wird dieses Attribut beim Anlegen des Objekts nicht als Parameter
   übergeben, wird es beim ersten Zugriff oder beim Lesen des ersten
   Datensatzes aus der Datei initialisiert.


Writer-Objekte
==============

Objekte von "writer" (Instanzen von "DictWriter" und Objekte, die von
der Funktion "writer()" zurückgegeben werden) haben die folgenden
öffentlichen Methoden. Bei Objekten von "writer" muss eine *row* ein
iterierbares Objekt aus Zeichenketten oder Zahlen sein, bei Objekten
von "DictWriter" ein Dictionary, das Feldnamen auf Zeichenketten oder
Zahlen abbildet (die zuvor mit "str()" umgewandelt werden). Beachte,
dass komplexe Zahlen in runde Klammern eingeschlossen ausgegeben
werden. Das kann bei anderen Programmen, die CSV-Dateien lesen, zu
Problemen führen (sofern sie komplexe Zahlen überhaupt unterstützen).

csvwriter.writerow(row)

   Schreibe den Parameter *row* in das Dateiobjekt des Writers,
   formatiert gemäß dem aktuellen "Dialect". Gib den Rückgabewert des
   Aufrufs der Methode *write* des zugrunde liegenden Dateiobjekts
   zurück.

   Geändert in Version 3.5: Unterstützung für beliebige iterierbare
   Objekte hinzugefügt.

csvwriter.writerows(rows)

   Schreibe alle Elemente in *rows* (eine iterierbare Struktur aus
   *row*-Objekten, wie oben beschrieben) in das Dateiobjekt des
   Writers, formatiert gemäß dem aktuellen Dialekts

Writer-Objekte haben die folgende öffentliche Attribut:

csvwriter.dialect

   Eine rein informative Beschreibung des vom Verfasser verwendeten
   Dialekts.

DictWriter-Objekte verfügen über die folgende öffentliche Methode:

DictWriter.writeheader()

   Schreibt eine Zeile mit den Feldnamen (wie im Konstruktor
   angegeben) in das Dateiobjekt des Schreibers, formatiert gemäß dem
   aktuellen Dialekt. Gibt den Rückgabewert des intern verwendeten
   Aufrufs von "csvwriter.writerow()" zurück.

   Neu in Version 3.2.

   Geändert in Version 3.8: "writeheader()" gibt nun auch den Wert
   zurück, den die intern verwendete Methode "csvwriter.writerow()"
   zurückgibt.


Beispiele
=========

Das einfachste Beispiel für das Einlesen einer CSV-Datei:

   import csv
   with open('some.csv', newline='') as f:
       reader = csv.reader(f)
       for row in reader:
           print(row)

Eine Datei in einem anderen Format lesen:

   import csv
   with open('passwd', newline='') as f:
       reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
       for row in reader:
           print(row)

Das entsprechende einfachste Beispiel zum Schreiben lautet:

   import csv
   with open('some.csv', 'w', newline='') as f:
       writer = csv.writer(f)
       writer.writerows(someiterable)

Da eine CSV-Datei zum Lesen mit "open()" geöffnet wird, wird sie
standardmäßig mit der Standardkodierung des Systems nach Unicode
dekodiert (siehe "locale.getencoding()"). Um eine Datei mit einer
anderen Kodierung zu dekodieren, verwende das Argument "encoding" von
open:

   import csv
   with open('some.csv', newline='', encoding='utf-8') as f:
       reader = csv.reader(f)
       for row in reader:
           print(row)

Dasselbe gilt für das Schreiben in einer anderen als der
Standardkodierung des Systems: Gib beim Öffnen der Ausgabedatei das
Argument encoding an.

Einen neuen Dialekt registrieren:

   import csv
   csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
   with open('passwd', newline='') as f:
       reader = csv.reader(f, 'unixpwd')

Eine etwas fortgeschrittenere Anwendung des Readers – Fehler erkennen
und melden:

   import csv, sys
   filename = 'some.csv'
   with open(filename, newline='') as f:
       reader = csv.reader(f)
       try:
           for row in reader:
               print(row)
       except csv.Error as e:
           sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))

Und obwohl das Modul das Parsen von Zeichenketten nicht direkt
unterstützt, lässt sich dies problemlos bewerkstelligen:

   import csv
   for row in csv.reader(['one,two,three']):
       print(row)

-[ Fußnoten ]-

[1] If "newline=''" is not specified, newlines embedded inside quoted
    fields will not be interpreted correctly, and on platforms that
    use "\r\n" linendings on write an extra "\r" will be added.  It
    should always be safe to specify "newline=''", since the csv
    module does its own (*universal*) newline handling.
