是否可以使用 with 直接使用CSV文件进行声明?能够做这样的事情似乎很自然:

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语句兼容?

有帮助吗?

解决方案

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

csv.reader 如果有例外,请清理工作吗?

我会选择:

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

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

import contextlib

在模块中帮助函数上下文manager contextlib:

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.

其他提示

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

至于为什么?谁知道。您是对的,这可能是一个容易的变化。它不如其他事情那么优先。

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

问题是csv.Reader并没有真正管理上下文。它可以接受任何可观的,而不仅仅是文件。因此,它不会在其输入上关闭(顺便说一句,如果您可以使用ContextLib.Closing)。因此,对于CSV.Reader实际上会有哪些上下文支持并不明显。

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

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


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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top