21 Stimmen

Die Verwendung des "with"-Statements für CSV-Dateien in Python

Ist es möglich, das with-Statement direkt mit CSV-Dateien zu verwenden? Es scheint natürlich zu sein, etwas wie das Folgende zu tun:

import csv
with csv.reader(open("myfile.csv")) as reader:
    # do things with reader

Aber csv.reader stellt nicht die Methoden __enter__ und __exit__ bereit, daher funktioniert dies nicht. Ich kann es jedoch in zwei Schritten machen:

import csv
with open("myfile.csv") as f:
    reader = csv.reader(f)
    # do things with reader

Ist diese zweite Möglichkeit der ideale Weg, um es zu tun? Warum haben sie csv.reader nicht direkt mit dem with-Statement kompatibel gemacht?

21voto

jfs Punkte 370717

Die primäre Verwendung des with-Statements liegt im ausnahme-sicheren Bereinigen eines in dem Statement verwendeten Objekts. with stellt sicher, dass Dateien geschlossen, Sperren freigegeben, Kontexte wiederhergestellt usw. werden.

Muss csv.reader Sachen aufräumen, falls eine Ausnahme auftritt?

Ich würde Folgendes verwenden:

with open("meinedatei.csv") as f:
    for row in csv.reader(f):
        # Zeile verarbeiten

Sie müssen den Patch nicht einreichen, um csv.reader und with-Statement zusammen zu verwenden.

import contextlib

Hilfe zu Funktion contextmanager in Modul contextlib:

contextmanager(func)
    Dekorator für @contextmanager.

Typische Verwendung:

    @contextmanager
    def some_generator():

        try:
            yield 
        finally:

Dadurch wird dies:

    with some_generator() as :

äquivalent zu diesem:

    try:
         = 

    finally:

Hier ist ein konkretes Beispiel, wie ich es verwendet habe: curses_screen.

4voto

S.Lott Punkte 371691

Ja. Der zweite Weg ist korrekt.

Warum? Wer weiß das schon. Du hast recht, es ist wahrscheinlich eine einfache Änderung. Es hat nicht so hohe Priorität wie andere Dinge.

Du kannst ganz einfach dein eigenes Patch-Kit erstellen und es einreichen.

2voto

A. Coady Punkte 49113

Das Problem ist, dass csv.reader nicht wirklich einen Kontext verwaltet. Es kann beliebige Iterables akzeptieren, nicht nur eine Datei. Daher ruft es close nicht auf seinem Eingang auf (übrigens, wenn es das täte, könnten Sie contextlib.closing verwenden). Es ist also nicht offensichtlich, was Kontextunterstützung für csv.reader tatsächlich tun würde.

1voto

user3964 Punkte 19
import csv

class CSV(object):
    def __init__(self, path, mode):
        self.path = path
        self.mode = mode
        self.file = None

    def __enter__(self):
        self.file = open(self.path, self.mode)
        if self.mode == 'r':
            return csv.reader(self.file)
        elif self.mode == 'w':
            return csv.writer(self.file)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

with CSV('data.csv','r') as reader:
    for row in reader:
        print row

0voto

user26294 Punkte 5105

Es ist einfach, das zu erstellen, was Sie wollen, indem Sie eine Generatorfunktion verwenden:

import csv
from contextlib import contextmanager

@contextmanager
def opencsv(path):
   yield csv.reader(open(path))

with opencsv("myfile.csv") as reader:
   # do stuff with your csvreader

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X