You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决csv.writer在with块中调用stdout时的__exit__属性错误?

解决csv.writer无法直接用在with语句的问题

嘿,这个坑我之前踩过!咱们先搞清楚为啥报错:csv.writer对象本身不是上下文管理器——它没有__exit__方法,而with语句要求被管理的对象必须实现__enter__和__exit__这两个方法来处理资源的打开和清理,所以直接写with csv.writer(...) as file就会抛出AttributeError: __exit__。

下面给你几个Python里的优雅解决办法,类似Ruby里的简洁写法:

方案1:最规范的Pythonic写法(推荐)

把文件对象的上下文管理和csv.writer的创建分开,让with负责管好文件资源,csv.writer专注处理格式:

import csv
import sys

stdout = sys.stdout
output = "your_output.csv"  # 或者设为"stdout"

with open(output, "w") if output != 'stdout' else stdout as file:
    writer = csv.writer(file)
    # 这里写你的写入逻辑
    writer.writerow(["姓名", "年龄"])
    writer.writerow(["张三", 25])

这种写法清晰又安全,with会自动帮你关闭磁盘文件(如果是stdout的话就不用关,毕竟是系统标准输出)。

方案2:自定义上下文管理器(封装成类似Ruby的块风格)

如果你想把csv.writer直接包装成可在with里用的对象,可以用contextlib.contextmanager写个简单的装饰器,把文件的打开、写入、关闭逻辑封装起来:

from contextlib import contextmanager
import csv
import sys

stdout = sys.stdout

@contextmanager
def csv_writer(output):
    # 打开文件或者用stdout
    file = open(output, "w") if output != 'stdout' else stdout
    try:
        # 返回csv.writer对象给with语句使用
        yield csv.writer(file)
    finally:
        # 只有磁盘文件需要关闭,别碰stdout!
        if output != 'stdout':
            file.close()

# 使用起来就像直接管理csv.writer一样
with csv_writer("output.csv") as writer:
    writer.writerow(["col1", "col2"])
with csv_writer("stdout") as writer:
    writer.writerow(["hello", "from", "stdout"])

这个就和Ruby里自定义块的思路很像,把重复的逻辑封装起来,用的时候更简洁。

为啥前两种写法没问题?

你之前写的:

with (open(output, "w")) if output != 'stdout' else stdout as file:

和

file = csv.writer(open(output, "w") if output != 'stdout' else stdout)

第一种是with直接管理文件对象(open()返回的是上下文管理器),第二种是直接创建csv.writer但没用到with(不过注意第二种写法如果是磁盘文件的话,需要手动调用file.close(),不然可能会有资源泄漏)。

内容的提问来源于stack exchange,提问作者PapeK24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:35:53