Python/Django无法通过TempFile发邮件:‘_io.TextIOWrapper’无splitlines属性
解决Tempfile写入后无法读取作为邮件附件的问题
我之前也踩过完全一样的坑!用Tempfile生成CSV想直接当邮件附件发出去,明明写完了内容,结果读不出来还报'_io.TextIOWrapper' object has no attribute 'splitlines'的错,折腾了好一会儿才搞明白问题出在哪。
问题根源
你遇到的核心问题有两个:
- 文件指针位置不对:当你用
csv.writer写完内容后,文件的读写指针停在了文件的末尾,这时候直接调用read()会返回空内容,邮件处理附件时自然会报错。 - 文件打开模式不匹配:如果你的临时文件是用只写模式打开的,那根本没法读取内容;另外邮件附件处理对文本/二进制模式的要求也得对应上。
解决方案
直接上能跑的代码示例,结合Django的邮件发送来演示:
import csv import tempfile from django.core.mail import EmailMessage def queryset_to_csv_email(queryset, recipient): # 用w+模式创建临时文件:可读可写,文本模式,指定换行符避免CSV换行问题 with tempfile.NamedTemporaryFile(mode='w+', newline='', encoding='utf-8', delete=False) as temp_file: # 初始化CSV写入器 csv_writer = csv.writer(temp_file) # 1. 写入表头:替换成你的模型字段名 model_fields = ['id', 'name', 'created_at'] csv_writer.writerow(model_fields) # 2. 写入QuerySet数据 for instance in queryset: csv_writer.writerow([getattr(instance, field) for field in model_fields]) # 关键操作:把文件指针移回文件开头! temp_file.seek(0) # 3. 准备邮件并添加附件 email = EmailMessage( subject='你的CSV数据已生成', body='附件是你请求的数据集,请查收', from_email='noreply@yourdomain.com', to=[recipient] ) # 读取CSV内容并添加为附件 csv_content = temp_file.read() email.attach( filename='dataset.csv', content=csv_content, mimetype='text/csv' ) # 发送邮件 email.send(fail_silently=False)
几个关键细节要注意:
seek(0)必须加:写完所有内容后,一定要调用这个方法把指针重置到文件开头,不然read()只会读到空字符串。- 文件模式选对:用
w+模式确保文件可读可写;如果是处理二进制内容可以用w+b,但CSV用文本模式更稳妥,记得指定encoding和newline避免乱码或换行问题。 delete=False(可选):默认临时文件关闭后会被删除,如果需要调试的话可以加这个参数,文件会保留下来方便你查看内容是否正确。
如果还是有问题,你可以在seek(0)之后先打印一下temp_file.read()的内容,确认是不是真的读到了数据——要是输出空的,那大概率还是指针没移对或者模式不对。
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

