21

是否可以将with语句直接用于 CSV 文件?能够做这样的事情似乎很自然:

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

但是 csv.reader 不提供__enter__and__exit__方法,所以这不起作用。但是,我可以分两步完成:

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

这第二种方式是理想的方式吗?他们为什么不让 csv.reader 直接与 with 语句兼容?

4

5 回答 5

21

语句的主要用途是对with语句中使用的对象进行异常安全的清理。with确保关闭文件、释放锁、恢复上下文等。

如果出现异常, csv.reader是否有需要清理的东西?

我会去:

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

您无需将补丁使用csv.readerwith声明一起提交。

import contextlib

关于模块contextlib中函数 contextmanager 的帮助:

contextmanager(func)
    @contextmanager decorator.

典型用法:

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

这使得:

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

相当于:

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

这是我如何使用它的具体示例:curses_screen

于 2009-01-14T00:24:41.657 回答
4

是的。第二种方法是正确的。

至于为什么?谁知道。你是对的,这可能是一个简单的改变。它不像其他事情那样优先。

您可以轻松制作自己的补丁包并提交。

于 2009-01-13T22:45:20.360 回答
2

问题是 csv.reader 并没有真正管理上下文。它可以接受任何可迭代的,而不仅仅是文件。因此它不会在其输入上调用 close(顺便说一下,如果它调用了,您可以使用 contextlib.closure)。因此,对 csv.reader 的上下文支持实际上会做什么并不明显。

于 2009-01-14T04:57:06.507 回答
1
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
于 2011-06-01T21:11:58.500 回答
0

使用生成器函数很容易创建您想要的内容:


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
于 2009-01-14T02:01:06.800 回答