Pergunta

É possível usar o with Declaração diretamente com arquivos CSV? Parece natural poder fazer algo assim:

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

Mas o CSV.Reader não fornece o __enter__ e __exit__ Métodos, então isso não funciona. No entanto, posso fazer isso em duas etapas:

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

Esta é a segunda maneira da maneira ideal de fazer isso? Por que eles não tornariam o CSV. Reader diretamente compatível com a declaração com com?

Foi útil?

Solução

O uso primário de with A declaração é uma limpeza segura por exceção de um objeto usado na instrução. with Garanta que os arquivos estejam fechados, os bloqueios sejam liberados, os contextos são restaurados, etc.

Faz CSV.Reader Tem coisas para limpar em caso de exceção?

Eu iria com:

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

Você não precisa enviar o patch para usar csv.reader e with declaração juntos.

import contextlib

Ajuda na função contextManager no módulo contextlib:

contextmanager(func)
    @contextmanager decorator.

Uso típico:

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

Isso faz disso:

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

equivalente a isso:

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

Aqui está um exemplo concreto de como eu o usei: Curses_screen.

Outras dicas

Sim. A segunda maneira está correta.

Quanto a por quê? Quem já sabe. Você está certo, provavelmente é uma mudança fácil. Não é tão alta prioridade quanto outras coisas.

Você pode facilmente criar seu próprio kit de patch e enviá -lo.

O problema é que o CSV. Reader realmente não gerencia um contexto. Pode aceitar qualquer iterável, não apenas um arquivo. Portanto, ele não liga para fechar sua entrada (aliás, se o fizesse, você poderia usar o contextlib.closing). Portanto, não é óbvio qual suporte de contexto para o CSV. Reader realmente faria.

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

É fácil criar o que você deseja usando uma função de gerador:


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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top