Verwenden Sie die Anweisung „mit“ für CSV -Dateien in Python
-
22-07-2019 - |
Frage
Ist es möglich, die zu verwenden? with
Anweisung direkt mit CSV -Dateien? Es scheint natürlich, so etwas tun zu können:
import csv
with csv.reader(open("myfile.csv")) as reader:
# do things with reader
Aber csv.reader liefert das nicht __enter__
und __exit__
Methoden, also funktioniert das nicht. Ich kann es jedoch in zwei Schritten tun:
import csv
with open("myfile.csv") as f:
reader = csv.reader(f)
# do things with reader
Ist dieser zweite Weg der ideale Weg, dies zu tun? Warum sollten sie CSV.reader nicht direkt mit der With -Erklärung kompatibel machen?
Lösung
Die primäre Verwendung von with
Die Anweisung ist eine ausnahmslos sichere Reinigung eines in der Anweisung verwendeten Objekts. with
stellt sicher, dass die Dateien geschlossen sind, Sperren veröffentlicht werden, Kontexte wiederhergestellt werden usw.
Tut csv.reader Haben Sie in Ausnahme die Dinge aufräumen?
Ich würde mit:
with open("myfile.csv") as f:
for row in csv.reader(f):
# process row
Sie müssen den Patch nicht einreichen, um sie zu verwenden csv.reader
und with
Aussage zusammen.
import contextlib
Hilfe bei Funktionskontextmanager im Modul Kontextlib:
contextmanager(func)
@contextmanager decorator.
Typische Verwendung:
@contextmanager
def some_generator(<arguments>):
<setup>
try:
yield <value>
finally:
<cleanup>
Dies macht das:
with some_generator(<arguments>) as <variable>:
<body>
entspricht dem:
<setup>
try:
<variable> = <value>
<body>
finally:
<cleanup>
Hier ist ein konkretes Beispiel, wie ich es verwendet habe: Flüche_Screen.
Andere Tipps
Ja. Der zweite Weg ist korrekt.
Warum? Wer weiß jemals. Sie haben Recht, es ist wahrscheinlich eine einfache Veränderung. Es ist nicht so hochrangig wie andere Dinge.
Sie können problemlos Ihr eigenes Patch -Kit erstellen und einreichen.
Das Problem ist, dass CSV.reader einen Kontext nicht wirklich verwaltet. Es kann iterable, nicht nur eine Datei akzeptieren. Daher ruft es seine Eingabe nicht in die Nähe des Eingangs (wenn es sich um contextlib.closing verwenden kann) nicht an. Es ist also nicht offensichtlich, welche Kontextunterstützung für CSV.reader tatsächlich tun würde.
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
Es ist einfach, das zu erstellen, was Sie mit einer Generatorfunktion möchten:
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