将csv数据转换为dict,而无需将文件写入磁盘

问题描述

这是我的情况:我有一个requests下载的zip文件到内存中,而不是写一个文件。我正在将数据解压缩到名为myzipfile的对象中。压缩文件中是一个csv文件。我想将csv数据的每一行转换成字典。这是我到目前为止所拥有的。

import csv
from io import BytesIO
import requests

# other imports etc. 

        r = requests.get(url=fileurl,headers=headers,stream=True)
        filebytes = BytesIO(r.content)

        myzipfile = zipfile.ZipFile(filebytes)
        for name in myzipfile.namelist():  
            mycsv = myzipfile.open(name).read()
            for row in csv.DictReader(mycsv):  # it fails here.
                print(row)

错误

Traceback (most recent call last):
  File "/usr/lib64/python3.7/csv.py",line 98,in fieldnames
    self._fieldnames = next(self.reader)
_csv.Error: iterator should return strings,not int (did you open the file in text mode?)

看起来像csv.DictReader(mycsv)期望使用文件对象而不是原始数据。如何将mycsv对象数据(<class 'bytes'>)中的行转换为词典列表?我试图做到这一点而不将文件写入磁盘并直接从内存中的csv对象工作。

解决方法

dict_list = [] # a list
reader = csv.DictReader(open('yourfile.csv','rb'))
for line in reader: # since we used DictReader,each line will be saved as a dictionary
 dict_list.append(line)
,

DictReader需要一个文件或类似文件的对象:我们可以通过将压缩文件加载到io.StringIO实例中来满足此期望。

请注意,StringIO期望其参数为str,但是从zip文件读取文件将返回bytes,因此必须对数据进行解码。本示例假定csv最初是使用本地系统的默认编码进行编码的。如果不是这种情况,必须将正确的编码传递给decode()

for name in myzipfile.namelist():
    data = myzipfile.open(name).read().decode()
    mycsv = io.StringIO(data)
    reader = csv.DictReader(mycsv)
    for row in reader:
        print(row)