2009-01-13 44 views
17

是否可以直接将with语句用于CSV文件?他很自然地能够做到这样的事情:在Python中对CSV文件使用“with”语句

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

但csv.reader不提供__enter____exit__方法,所以这是行不通的。但我可以分两步做:

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

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

+0

如下所述,它对csv阅读器没有任何意义。但是这对于作家来说确实如此! – b0fh 2017-07-31 08:05:53

回答

18

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

csv.reader是否有异常情况下的清理?

我会去用:

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

你并不需要提交使用csv.readerwith声明一起补丁。

import 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

3

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

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

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

+0

好的,也许我会那样做。谢谢。 – Kiv 2009-01-13 22:52:59

+1

我不确定这是一个“可修补的进攻”。CSV阅读器的目的是对一个开放的文件对象进行操作,并提供一系列的行 - 没有真正的资源获取和发布。如果您想快速跳出with block,请执行rows = list(csv.reader(file_))并使用它之外的行。 – cdleary 2009-01-14 07:16:44

+0

@cdleary:我认为回应并不一定反映ACTUAL资源的使用情况,而只是“资源”状。所有的“数据压缩”和“文件格式”库模块都应该这样做,以获得简单的一致性。 – 2009-01-14 11:21:37

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 
2

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

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