Question

Est-il possible d'utiliser l'instruction avec directement avec des fichiers CSV? Il semble naturel de pouvoir faire quelque chose comme ceci:

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

Mais csv.reader ne fournit pas les méthodes __ enter __ et __ exit __ , donc cela ne fonctionne pas. Je peux cependant le faire en deux étapes:

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

Est-ce que cette deuxième façon est la manière idéale de le faire? Pourquoi ne rendraient-ils pas csv.reader directement compatible avec l'instruction with?

Était-ce utile?

La solution

L'utilisation principale de avec l'instruction est un nettoyage protégé contre les exceptions d'un objet utilisé dans l'instruction. avec permet de s'assurer que les fichiers sont fermés, que les verrous sont libérés, que les contextes sont restaurés, etc.

csv.reader a-t-il des choses à nettoyer en cas de exception?

J'irais avec:

with open("myfile.csv") as f:
    for row in csv.reader(f):
        # process row

Il n'est pas nécessaire de soumettre le correctif pour utiliser simultanément csv.reader et avec .

import contextlib

Aide sur la fonction contextmanager dans le module contextlib :

contextmanager(func)
    @contextmanager decorator.

Utilisation typique:

    @contextmanager
    def some_generator(<arguments>):
        <setup>
        try:
            yield <value>
        finally:
            <cleanup>

Cela fait ceci:

    with some_generator(<arguments>) as <variable>:
        <body>

équivalent à ceci:

    <setup>
    try:
        <variable> = <value>
        <body>
    finally:
        <cleanup>

Voici un exemple concret d'utilisation de ce logiciel: curses_screen .

Autres conseils

Oui. La deuxième façon est correcte.

Quant à pourquoi? Qui sait jamais. Vous avez raison, c'est probablement un changement facile. Ce n’est pas aussi prioritaire que d’autres choses.

Vous pouvez facilement créer votre propre kit de correctifs et le soumettre.

Le problème est que csv.reader ne gère pas vraiment un contexte. Il peut accepter tout type de données, pas seulement un fichier. Par conséquent, il n'appelle pas close sur son entrée (d'ailleurs, si c'était le cas, vous pourriez utiliser contextlib.closing). Il n’est donc pas évident de savoir quel support de contexte pour csv.reader ferait réellement.

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

Il est facile de créer ce que vous voulez en utilisant une fonction de générateur:


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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top