"csv" --- Ανάγνωση και Εγγραφή Αρχείων CSV
******************************************

**Πηγαίος κώδικας:** Lib/csv.py

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

Το λεγόμενο CSV (Comma Separated Values) είναι η πιο κοινή μορφή
εισαγωγής και εξαγωγής για υπολογιστικά φύλλα και βάσεις δεδομένων. Η
μορφή CSV χρησιμοποιήθηκε για πολλά χρόνια πριν από τις προσπάθειες
περιγραφής της μορφής με έναν τυποποιημένο τρόπο στο **RFC 4180**. Η
έλλειψη ενός καλά καθορισμένου προτύπου σημαίνει ότι συχνά υπάρχουν
λεπτές διαφορές στα δεδομένα που παράγονται και καταναλώνονται από
διαφορετικές εφαρμογές. Αυτές οι διαφορές μπορούν να κάνουν ενοχλητική
την επεξεργασία αρχείων CSV από πολλαπλές πηγές. Ωστόσο, ενώ οι
διαχωριστές και οι χαρακτήρες παράθεσης ποικίλλουν, η συνολική μορφή
είναι αρκετά παρόμοια ώστε να είναι δυνατό να γραφτεί ένα ενιαίο
module που μπορεί να χειριστεί αποτελεσματικά αυτά τα δεδομένα,
κρύβοντας τις λεπτομέρειες της ανάγνωσης και εγγραφής των δεδομένων
από τον προγραμματιστή.

Το module "csv" υλοποιεί κλάσεις για την ανάγνωση και εγγραφή
δομημένων δεδομένων σε μορφή CSV. Επιτρέπει στους προγραμματιστές να
δηλώνουν, "γράψε αυτά τα δεδομένα στη μορφή που προτιμάται το Excel,"
ή "διάβασε δεδομένα από αυτό το αρχείο που δημιουργήθηκε από το
Excel," χωρίς να γνωρίζουν τις ακριβείς λεπτομέρειες της μορφής CSV
που χρησιμοποιείται από το Excel. Οι προγραμματιστές μπορούν επίσης να
περιγράψουν τις μορφές CSV που κατανοούνται από άλλες εφαρμογές ή να
ορίσουν τις δικές τους ειδικές μορφές CSV.

Τα αντικείμενα "reader" και "writer" του module "csv" διαβάζουν και
γράφουν ακολουθίες. Οι προγραμματιστές μπορούν επίσης να διαβάσουν και
να γράψουν δεδομένα σε μορφή λεξικού χρησιμοποιώντας τις κλάσεις
"DictReader" και "DictWriter".

Δείτε επίσης:

  **PEP 305** - API Αρχείων CSV
     Η Πρόταση Βελτίωσης της Python που πρότεινε αυτή την προσθήκη
     στην Python.


Περιεχόμενα του Module
======================

Το module "csv" ορίζει τις παρακάτω συναρτήσεις:

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

   Επιστρέφει ένα αντικείμενο reader που θα επεξεργάζεται γραμμές από
   το δεδομένο *csvfile*. Ένα csvfile πρέπει να είναι μια ακολουθία
   από συμβολοσειρές, κάθε μια στη μορφή CSV που ορίζει ο αναγνώστης.
   Ένα csvfile είναι πιο συχνά ένα αντικείμενο παρόμοιο με αρχείο ή
   μια λίστα. Αν το *csvfile* είναι ένα αντικείμενο αρχείου, θα πρέπει
   να ανοιχτεί με "newline=''". [1] Μια προαιρετική παράμετρος
   *dialect* μπορεί να δοθεί η οποία χρησιμοποιείται για τον ορισμό
   ενός συνόλου παραμέτρων ειδικών για μια συγκεκριμένη διάλεκτο CSV.
   Μπορεί να είναι ένα στιγμιότυπο μιας υποκλάσης της κλάσης "Dialect"
   ή μια από τις συμβολοσειρές που επιστρέφει η συνάρτηση
   "list_dialects()". Οι άλλες προαιρετικές παράμετροι *fmtparams*
   μπορούν να δοθούν για να αντικαταστήσουν μεμονωμένες παραμέτρους
   μορφοποίησης στην τρέχουσα διάλεκτο. Για πλήρεις λεπτομέρειες
   σχετικά με τις διαλέκτους και τις παραμέτρους μορφοποίησης, δείτε
   την ενότητα Διάλεκτοι και Παράμετροι Μορφοποίησης.

   Κάθε γραμμή που διαβάζεται από το αρχείο csv επιστρέφεται ως μια
   λίστα συμβολοσειρών. Δεν γίνεται αυτόματη μετατροπή τύπων δεδομένων
   εκτός αν οριστεί η επιλογή μορφοποίησης "QUOTE_NONNUMERIC" (στην
   οποία περίπτωση τα μη παρατεθειμένα πεδία μετατρέπονται σε float).

   Ένα σύντομο παράδειγμα χρήσης:

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

   Επιστρέφει ένα αντικείμενο writer υπεύθυνο για τη μετατροπή των
   δεδομένων του χρήστη σε διαχωρισμένες συμβολοσειρές στο δεδομένο
   αντικείμενο παρόμοιο με αρχείο. Το *csvfile* μπορεί να είναι
   οποιοδήποτε αντικείμενο με μια μέθοδο "write()". Αν το *csvfile*
   είναι ένα αντικείμενο αρχείου, θα πρέπει να ανοιχτεί με
   "newline=''" [1]. Μια προαιρετική παράμετρος *dialect* μπορεί να
   δοθεί η οποία χρησιμοποιείται για τον ορισμό ενός συνόλου
   παραμέτρων ειδικών για μια συγκεκριμένη διάλεκτο CSV. Μπορεί να
   είναι ένα στιγμιότυπο μιας υποκλάσης της κλάσης "Dialect" ή μια από
   τις συμβολοσειρές που επιστρέφει η συνάρτηση "list_dialects()". Οι
   άλλες προαιρετικές παράμετροι *fmtparams* μπορούν να δοθούν για να
   αντικαταστήσουν μεμονωμένες παραμέτρους μορφοποίησης στην τρέχουσα
   διάλεκτο. Για πλήρεις λεπτομέρειες σχετικά με τις διαλέκτους και
   τις παραμέτρους μορφοποίησης, δείτε την ενότητα Διάλεκτοι και
   Παράμετροι Μορφοποίησης. Για να διευκολυνθεί όσο το δυνατόν
   περισσότερο η διασύνδεση με modules που υλοποιούν το DB API, η τιμή
   "None" γράφεται ως η κενή συμβολοσειρά. Ενώ αυτή δεν είναι μια
   αντιστρέψιμη μετατροπή, διευκολύνει την εξαγωγή τιμών NULL SQL σε
   αρχεία CSV χωρίς προεπεξεργασία των δεδομένων που επιστρέφονται από
   μια κλήση *cursor.fetch**. Όλα τα άλλα μη-συμβολοσειριακά δεδομένα
   μετατρέπονται σε συμβολοσειρές με τη χρήση της "str()" πριν
   γραφούν.

   Ένα σύντομο παράδειγμα χρήσης:

      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='excel', **fmtparams)

   Συσχετίζει το *dialect* με το *name*. Το *name* πρέπει να είναι μια
   συμβολοσειρά. Η διάλεκτος μπορεί να καθοριστεί είτε περνώντας μια
   υποκλάση της "Dialect", είτε με παραμέτρους *fmtparams* ως
   ορίσματα, είτε και τα δύο, με τις παραμέτρους *fmtparams* να
   αντικαθιστούν τις παραμέτρους της διαλέκτου. Για πλήρεις
   λεπτομέρειες σχετικά με τις διαλέκτους και τις παραμέτρους
   μορφοποίησης, δείτε την ενότητα Διάλεκτοι και Παράμετροι
   Μορφοποίησης.

csv.unregister_dialect(name)

   Διαγράφει τη διάλεκτο που συσχετίζεται με το *name* από το μητρώο
   διαλέκτων. Μια "Error" γίνεται raise αν το *name* δεν είναι ένα
   καταχωρημένο όνομα διαλέκτου.

csv.get_dialect(name)

   Επιστρέφει τη διάλεκτο που συσχετίζεται με το *name*. Μια "Error"
   γίνεται raise αν το *name* δεν είναι ένα καταχωρημένο όνομα
   διαλέκτου. Αυτή η συνάρτηση επιστρέφει μια αμετάβλητη "Dialect".

csv.list_dialects()

   Επιστρέφει τα ονόματα όλων των καταχωρημένων διαλέκτων.

csv.field_size_limit()
csv.field_size_limit(new_limit)

   Επιστρέφει το τρέχον μέγιστο μέγεθος πεδίου που επιτρέπεται από τον
   αναλυτή. Αν δοθεί *new_limit*, αυτό γίνεται το νέο όριο.

Το module "csv" ορίζει τις παρακάτω κλάσεις:

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

   Δημιουργεί ένα αντικείμενο που λειτουργεί όπως ένας κανονικός
   αναγνώστης αλλά χαρτογραφεί τις πληροφορίες σε κάθε γραμμή σε ένα
   "dict" των οποίων τα κλειδιά δίνονται από την προαιρετική παράμετρο
   *fieldnames*.

   Η παράμετρος *fieldnames* είναι μια *sequence*. Αν το *fieldnames*
   έχει παραληφθεί, οι τιμές στην πρώτη γραμμή του αρχείου *f* θα
   χρησιμοποιηθούν ως τα ονόματα πεδίων και θα παραλειφθούν από τα
   αποτελέσματα. Αν το *fieldnames* παρέχεται, θα χρησιμοποιηθούν και
   η πρώτη γραμμή θα περιληφθεί στα αποτελέσματα. Ανεξάρτητα από το
   πώς καθορίζονται τα ονόματα πεδίων, το λεξικό διατηρεί την αρχική
   τους σειρά.

   Αν μια γραμμή έχει περισσότερα πεδία από τα ονόματα πεδίων, τα
   υπόλοιπα δεδομένα τοποθετούνται σε μια λίστα και αποθηκεύονται με
   το όνομα πεδίου που καθορίζεται από το *restkey* (το οποίο
   προεπιλέγεται σε "None"). Αν μια μη-κενή γραμμή έχει λιγότερα πεδία
   από τα ονόματα πεδίων, οι ελλείπουσες τιμές συμπληρώνονται με την
   τιμή του *restval* (το οποίο προεπιλέγεται σε "None").

   Όλες οι άλλες προαιρετικές ή παράμετροι λέξεων-κλειδιών
   μεταβιβάζονται στο υποκείμενο αντικείμενο "reader".

   Αν το όρισμα που δίνεται στο *fieldnames* είναι ένας iterator, θα
   μετατραπεί σε μια "list".

   Άλλαξε στην έκδοση 3.6: Οι επιστρεφόμενες γραμμές είναι τώρα τύπου
   "OrderedDict".

   Άλλαξε στην έκδοση 3.8: Οι επιστρεφόμενες γραμμές είναι τώρα τύπου
   "dict".

   Ένα σύντομο παράδειγμα χρήσης:

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

   Δημιουργεί ένα αντικείμενο που λειτουργεί όπως ένας κανονικός
   εγγραφέας αλλά χαρτογραφεί λεξικά σε εξαγόμενες γραμμές. Η
   παράμετρος *fieldnames* είναι μια "sequence" κλειδιών που
   προσδιορίζουν τη σειρά στην οποία οι τιμές στο λεξικό που
   περνιούνται στη μέθοδο "writerow()" γράφονται στο αρχείο *f*. Η
   προαιρετική παράμετρος *restval* καθορίζει την τιμή που θα γραφτεί
   αν από το λεξικό λείπει ένα κλειδί στα  *fieldnames*. Αν το λεξικό
   που περνιέται στη μέθοδο "writerow()" περιέχει ένα κλειδί που δεν
   βρίσκεται στα *fieldnames*, η προαιρετική παράμετρος *extrasaction*
   υποδεικνύει ποια ενέργεια να ληφθεί. Αν οριστεί σε "'raise'", η
   προεπιλεγμένη τιμή, γίνεται raise μια "ValueError". Αν οριστεί σε
   "'ignore'", οι επιπλέον τιμές στο λεξικό αγνοούνται. Οποιεσδήποτε
   άλλες προαιρετικές ή παράμετροι λέξεων-κλειδιών μεταβιβάζονται στο
   υποκείμενο αντικείμενο "writer".

   Σημειώστε ότι σε αντίθεση με την κλάση "DictReader", η παράμετρος
   **fieldnames** της κλάσης "DictWriter" δεν είναι προαιρετική.

   Αν το όρισμα που δίνεται στο *fieldnames* είναι ένας iterator, θα
   μετατραπεί σε μια "list".

   Ένα σύντομο παράδειγμα χρήσης:

      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

   Η κλάση "Dialect" είναι μια κλάση κοντέινερ των οποίων τα
   χαρακτηριστικά περιέχουν πληροφορίες για το πώς να χειριστούν τα
   διπλά εισαγωγικά, τα κενά, τους διαχωριστές κ.λπ. Λόγω της έλλειψης
   αυστηρής προδιαγραφής CSV, διαφορετικές εφαρμογές παράγουν λεπτές
   διαφορές στα δεδομένα CSV. Τα στιγμιότυπα της "Dialect" καθορίζουν
   πώς συμπεριφέρονται τα αντικείμενα "reader" και "writer".

   Όλα τα διαθέσιμα ονόματα "Dialect" επιστρέφονται από τη
   "list_dialects()", και μπορούν να καταχωρηθούν με συγκεκριμένες
   κλάσεις "reader" και "writer" μέσω των συναρτήσεων αρχικοποίησης
   ("__init__") τους όπως αυτό:

      import csv

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

class csv.excel

   Η κλάση "excel" ορίζει τις συνήθεις ιδιότητες ενός αρχείου CSV που
   δημιουργείται από το Excel. Είναι καταχωρημένη με το όνομα
   διαλέκτου "'excel'".

class csv.excel_tab

   Η κλάση "excel_tab" ορίζει τις συνήθεις ιδιότητες ενός αρχείου CSV
   που δημιουργείται από το Excel με διαχωριστικό TAB. Είναι
   καταχωρημένη με το όνομα διαλέκτου "'excel-tab'".

class csv.unix_dialect

   Η κλάση "unix_dialect" ορίζει τις συνήθεις ιδιότητες ενός αρχείου
   CSV που δημιουργείται σε συστήματα UNIX, δηλαδή χρησιμοποιεί "'\n'"
   ως τερματιστή γραμμής και παραθέτει όλα τα πεδία. Είναι
   καταχωρημένη με το όνομα διαλέκτου "'unix'".

   Added in version 3.2.

class csv.Sniffer

   Η κλάση "Sniffer" χρησιμοποιείται για να προσδιορίσει τη μορφή ενός
   αρχείου CSV.

   Η κλάση "Sniffer" παρέχει δύο μεθόδους:

   sniff(sample, delimiters=None)

      Αναλύει το δεδομένο *sample* και επιστρέφει μια υποκλάση της
      "Dialect" που αντικατοπτρίζει τις παραμέτρους που βρέθηκαν. Αν η
      προαιρετική παράμετρος *delimiters* δοθεί, ερμηνεύεται ως μια
      συμβολοσειρά που περιέχει πιθανά έγκυρους χαρακτήρες
      διαχωρισμού.

   has_header(sample)

      Αναλύει το δείγμα κειμένου (που θεωρείται ότι είναι σε μορφή
      CSV) και επιστρέφει "True" αν η πρώτη γραμμή φαίνεται να είναι
      μια σειρά κεφαλίδων στηλών. Εξετάζοντας κάθε στήλη, ένα από τα
      δύο βασικά κριτήρια θα εξεταστεί για να εκτιμηθεί αν το δείγμα
      περιέχει κεφαλίδα:

      * η δεύτερη έως την n-οστή γραμμή περιέχει αριθμητικές τιμές

      * η δεύτερη έως την n-οστή γραμμή περιέχει συμβολοσειρές όπου
        τουλάχιστον μία τιμή έχει μήκος διαφορετικό από αυτό της
        υποτιθέμενης κεφαλίδας αυτής της στήλης.

      Δείγμα λαμβάνεται από είκοσι γραμμές μετά την πρώτη γραμμή. Αν
      περισσότερες από τις μισές στήλες + γραμμές πληρούν τα κριτήρια,
      επιστρέφεται "True".

   Σημείωση:

     Αυτή η μέθοδος είναι μια χονδροειδής ευρετική και μπορεί να
     παράγει τόσο ψευδώς θετικά όσο και ψευδώς αρνητικά αποτελέσματα.

Ένα παράδειγμα χρήσης της "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 ...

Το module "csv" ορίζει τις παρακάτω σταθερές:

csv.QUOTE_ALL

   Οδηγεί τα αντικείμενα "writer" να παραθέτουν όλα τα πεδία.

csv.QUOTE_MINIMAL

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

csv.QUOTE_NONNUMERIC

   Οδηγεί τα αντικείμενα "writer" να παραθέτουν όλα τα μη-αριθμητικά
   πεδία.

   Οδηγεί τα αντικείμενα "reader" να μετατρέπουν όλα τα
   μη-παρατεθειμένα πεδία σε τύπο "float".

   Σημείωση:

     Ορισμένοι αριθμητικοί τύποι, όπως "bool", "Fraction", ή
     "IntEnum", έχουν μια αναπαράσταση συμβολοσειράς που δεν μπορεί να
     μετατραπεί σε "float". Δεν μπορούν να διαβαστούν σε λειτουργίες
     "QUOTE_NONNUMERIC" και "QUOTE_STRINGS".

csv.QUOTE_NONE

   Instructs "writer" objects to never quote fields. When the current
   *delimiter*, *quotechar*, *escapechar*, "'\r'", "'\n'" or any of
   the characters in *lineterminator* 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. Set *quotechar* to "None" to
   prevent its escaping.

   Οδηγεί τα αντικείμενα "reader" να μην εκτελούν ειδική επεξεργασία
   των χαρακτήρων παράθεσης.

csv.QUOTE_NOTNULL

   Οδηγεί τα αντικείμενα "writer" να παραθέτουν όλα τα πεδία που δεν
   είναι "None". Αυτό είναι παρόμοιο με "QUOTE_ALL", εκτός από το ότι
   αν μια τιμή πεδίου είναι "None", γράφεται μια κενή
   (μη-παρατεθειμένη) συμβολοσειρά.

   Οδηγεί τα αντικείμενα "reader" να ερμηνεύουν ένα κενό
   (μη-παρατεθειμένο) πεδίο ως "None" και να συμπεριφέρονται
   διαφορετικά ως "QUOTE_ALL".

   Added in version 3.12.

csv.QUOTE_STRINGS

   Οδηγεί τα αντικείμενα "writer" να τοποθετούν πάντα εισαγωγικά γύρω
   από πεδία που είναι συμβολοσειρές. Αυτό είναι παρόμοιο με
   "QUOTE_NONNUMERIC", εκτός από το ότι αν μια τιμή πεδίου είναι
   "None", γράφεται μια κενή (μη-παρατεθειμένη) συμβολοσειρά.

   Οδηγεί τα αντικείμενα "reader" να ερμηνεύουν μια κενή
   (μη-παρατεθειμένη) συμβολοσειρά ως "None" και να συμπεριφέρονται
   διαφορετικά ως "QUOTE_NONNUMERIC".

   Added in version 3.12.

Το module "csv" ορίζει την παρακάτω εξαίρεση:

exception csv.Error

   Γίνεται raise από οποιαδήποτε από τις συναρτήσεις όταν ανιχνεύεται
   ένα σφάλμα.


Διάλεκτοι και Παράμετροι Μορφοποίησης
=====================================

Για να διευκολυνθεί ο καθορισμός της μορφής των εγγραφών εισόδου και
εξόδου, οι συγκεκριμένες παράμετροι μορφοποίησης ομαδοποιούνται σε
διαλέκτους. Μια διάλεκτος είναι μια υποκλάση της κλάσης "Dialect" που
περιέχει διάφορα χαρακτηριστικά που περιγράφουν τη μορφή του αρχείου
CSV. Κατά τη δημιουργία αντικειμένων "reader" ή "writer", ο
προγραμματιστής μπορεί να καθορίσει μια συμβολοσειρά ή μια υποκλάση
της κλάσης "Dialect" ως παράμετρο διαλέκτου. Επιπλέον, αντί για ή
εκτός από την παράμετρο *dialect*, ο προγραμματιστής μπορεί επίσης να
καθορίσει μεμονωμένες παραμέτρους μορφοποίησης, οι οποίες έχουν τα
ίδια ονόματα με τα χαρακτηριστικά που ορίζονται παρακάτω για την κλάση
"Dialect".

Οι διάλεκτοι υποστηρίζουν τα παρακάτω χαρακτηριστικά:

Dialect.delimiter

   Μια συμβολοσειρά ενός χαρακτήρα που χρησιμοποιείται για να
   διαχωρίζει τα πεδία. Προεπιλογή είναι το "','".

Dialect.doublequote

   Ελέγχει πώς οι περιπτώσεις του *quotechar* που εμφανίζονται μέσα σε
   ένα πεδίο θα παρατίθενται. Όταν είναι "True", ο χαρακτήρας
   διπλασιάζεται. Όταν είναι "False", το *escapechar* χρησιμοποιείται
   ως πρόθεμα στο *quotechar*. Προεπιλογή είναι το "True".

   Στην έξοδο, αν το *doublequote* είναι "False" και δεν έχει οριστεί
   *escapechar*, γίνεται raise "Error" αν βρεθεί ένα *quotechar* σε
   ένα πεδίο.

Dialect.escapechar

   A one-character string used by the writer to escape characters that
   require escaping:

      * the *delimiter*, the *quotechar*, "'\r'", "'\n'" and any of
        the characters in *lineterminator* are escaped if *quoting* is
        set to "QUOTE_NONE";

      * the *quotechar* is escaped if *doublequote* is "False";

      * the *escapechar* itself.

   On reading, the *escapechar* removes any special meaning from the
   following character. It defaults to "None", which disables
   escaping.

   Άλλαξε στην έκδοση 3.11: Ένα κενό *escapechar* δεν επιτρέπεται.

Dialect.lineterminator

   Η συμβολοσειρά που χρησιμοποιείται για να τερματίσει τις γραμμές
   που παράγονται από τον "writer". Προεπιλογή είναι το "'\r\n'".

   Σημείωση:

     Ο "reader" είναι σκληρά κωδικοποιημένος για να αναγνωρίζει είτε
     "'\r'" είτε "'\n'" ως τερματισμό γραμμής, και αγνοεί το
     *lineterminator*. Αυτή η συμπεριφορά μπορεί να αλλάξει στο
     μέλλον.

Dialect.quotechar

   A one-character string used to quote fields containing special
   characters, such as the *delimiter* or the *quotechar*, or which
   contain new-line characters ("'\r'", "'\n'" or any of the
   characters in *lineterminator*). It defaults to "'"'". Can be set
   to "None" to prevent escaping "'"'" if *quoting* is set to
   "QUOTE_NONE".

   Άλλαξε στην έκδοση 3.11: Ένα κενό *quotechar* δεν επιτρέπεται.

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" if *quotechar* is not
   "None", and "QUOTE_NONE" otherwise.

Dialect.skipinitialspace

   When "True", spaces immediately following the *delimiter* are
   ignored. The default is "False".  When combining "delimiter=' '"
   with "skipinitialspace=True", unquoted empty fields are not
   allowed.

Dialect.strict

   Όταν είναι "True", γίνεται raise η εξαίρεση "Error" σε κακή είσοδο
   CSV. Η προεπιλογή είναι "False".


Αντικείμενα Αναγνώστη
=====================

Τα αντικείμενα αναγνώστη (στιγμιότυπα της "DictReader" και αντικείμενα
που επιστρέφονται από τη συνάρτηση "reader()") έχουν τις παρακάτω
δημόσιες μεθόδους:

csvreader.__next__()

   Επιστρέφει την επόμενη γραμμή του αντικειμένου iterable του
   αναγνώστη ως λίστα (αν το αντικείμενο επιστράφηκε από τη
   "reader()") ή ως λεξικό (αν είναι ένα στιγμιότυπο "DictReader"),
   αναλυμένο σύμφωνα με την τρέχουσα "Dialect". Συνήθως θα πρέπει να
   το καλέσετε ως "next(reader)".

Τα αντικείμενα αναγνώστη έχουν τα παρακάτω δημόσια χαρακτηριστικά:

csvreader.dialect

   Ένα μόνο για ανάγνωση περιγραφικό χαρακτηριστικό της διαλέκτου που
   χρησιμοποιείται από τον αναλυτή.

csvreader.line_num

   Ο αριθμός των γραμμών που διαβάστηκαν από τον πηγαίο επαναληπτή.
   Αυτό δεν είναι το ίδιο με τον αριθμό των εγγραφών που επιστράφηκαν,
   καθώς οι εγγραφές μπορούν να εκτείνονται σε πολλές γραμμές.

Τα αντικείμενα DictReader έχουν το παρακάτω δημόσιο χαρακτηριστικό:

DictReader.fieldnames

   Αν δεν περαστεί ως παράμετρος κατά τη δημιουργία του αντικειμένου,
   αυτό το χαρακτηριστικό αρχικοποιείται κατά την πρώτη πρόσβαση ή
   όταν διαβαστεί η πρώτη εγγραφή από το αρχείο.


Αντικείμενα Εγγραφέα
====================

Τα αντικείμενα "writer" (στιγμιότυπα της "DictWriter" και αντικείμενα
που επιστρέφονται από τη συνάρτηση "writer()") έχουν τις παρακάτω
δημόσιες μεθόδους. Ένα *row* πρέπει να είναι ένα επαναληπτικό
αντικείμενο συμβολοσειρών ή αριθμών για τα αντικείμενα "writer" και
ένα λεξικό που αντιστοιχεί τα ονόματα πεδίων σε συμβολοσειρές ή
αριθμούς (με πέρασμα μέσω της συνάρτησης "str()" πρώτα) για τα
αντικείμενα "DictWriter". Σημειώστε ότι οι σύνθετοι αριθμοί γράφονται
περιβαλλόμενοι από παρενθέσεις. Αυτό μπορεί να προκαλέσει κάποια
προβλήματα σε άλλα προγράμματα που διαβάζουν αρχεία CSV (υποθέτοντας
ότι υποστηρίζουν σύνθετους αριθμούς καθόλου).

csvwriter.writerow(row, /)

   Γράφει την παράμετρο *row* στο αντικείμενο αρχείου του εγγραφέα,
   μορφοποιημένο σύμφωνα με την τρέχουσα "Dialect". Επιστρέφει την
   τιμή επιστροφής της κλήσης στη μέθοδο *write* του υποκείμενου
   αντικειμένου αρχείου.

   Άλλαξε στην έκδοση 3.5: Προστέθηκε υποστήριξη για αυθαίρετα
   επαναληπτικά αντικείμενα.

csvwriter.writerows(rows, /)

   Γράφει όλα τα στοιχεία στο *rows* (ένα επαναληπτικό αντικείμενο των
   *row* αντικειμένων όπως περιγράφεται παραπάνω) στο αντικείμενο
   αρχείου του εγγραφέα, μορφοποιημένο σύμφωνα με την τρέχουσα
   διάλεκτο.

Τα αντικείμενα εγγραφέα έχουν το παρακάτω δημόσιο χαρακτηριστικό:

csvwriter.dialect

   Ένα μόνο για ανάγνωση περιγραφικό χαρακτηριστικό της διαλέκτου που
   χρησιμοποιείται από τον εγγραφέα.

Τα αντικείμενα DictWriter έχουν την παρακάτω δημόσια μέθοδο:

DictWriter.writeheader()

   Γράφει μια γραμμή με τα ονόματα πεδίων (όπως καθορίζονται στον
   κατασκευαστή) στο αντικείμενο αρχείου του εγγραφέα, μορφοποιημένο
   σύμφωνα με την τρέχουσα διάλεκτο. Επιστρέφει την τιμή επιστροφής
   της κλήσης "csvwriter.writerow()" που χρησιμοποιείται εσωτερικά.

   Added in version 3.2.

   Άλλαξε στην έκδοση 3.8: Η "writeheader()" τώρα επιστρέφει επίσης
   την τιμή που επιστρέφεται από τη μέθοδο "csvwriter.writerow()" που
   χρησιμοποιεί εσωτερικά.


Παραδείγματα
============

Το πιο απλό παράδειγμα ανάγνωσης ενός αρχείου CSV:

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

Ανάγνωση ενός αρχείου με εναλλακτική μορφή:

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

Το αντίστοιχο απλούστερο παράδειγμα εγγραφής είναι:

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

Αφού η "open()" χρησιμοποιείται για να ανοίξει ένα αρχείο CSV για
ανάγνωση, το αρχείο θα αποκωδικοποιηθεί κατά προεπιλογή σε unicode
χρησιμοποιώντας την προεπιλεγμένη κωδικοποίηση του συστήματος (βλ.
"locale.getencoding()"). Για να αποκωδικοποιήσετε ένα αρχείο
χρησιμοποιώντας μια διαφορετική κωδικοποίηση, χρησιμοποιήστε το όρισμα
"encoding" της open:

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

Το ίδιο ισχύει και για την εγγραφή σε κάτι άλλο εκτός από την
προεπιλεγμένη κωδικοποίηση του συστήματος: καθορίστε το όρισμα
κωδικοποίησης κατά το άνοιγμα του αρχείου εξόδου.

Καταχώρηση μιας νέας διαλέκτου:

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

Μια ελαφρώς πιο προηγμένη χρήση του αναγνώστη --- σύλληψη και αναφορά
σφαλμάτων:

   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(f'file {filename}, line {reader.line_num}: {e}')

Και ενώ το module δεν υποστηρίζει άμεσα την ανάλυση συμβολοσειρών,
μπορεί εύκολα να γίνει:

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

-[ Υποσημειώσεις ]-

[1] If "newline=''" is not specified, newlines embedded inside quoted
    fields will not be interpreted correctly, and on platforms that
    use "\r\n" line endings 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.
