我正在编写一个小脚本,它循环遍历.csv,将文件中的每一行存储为字典,并将该字典发送给一个一维列表中的API。
import csv
import requests
with open('csv.csv', 'rU') as f:
reader = csv.reader(f, skipinitialspace=True)
header = next(reader)
for row in reader:
request = [dict(zip(header, map(str, row)))]
r = requests.post(url, headers = i_headers, json = request)
print str(reader.line_num) + "-" + str(r)
request
列表看起来像这样:
[
{
"id": "1",
"col_1": "A",
"col_2": "B",
"col_3": "C"
}
]
这个脚本可以工作,但是我要遍历一个800万行的.csv文件,这个方法实在太慢了。我想通过每个API调用发送不止一行来加快这个过程。我正在使用的API允许我每次调用发送多达100行。
我如何改变这个脚本,以增量构建包含100个字典的列表,发布到API,然后重复。我将发送给这个API的示例如下:
[
{
"id": "1",
"col_1": "A",
"col_2": "B",
"col_3": "C"
},
{
"id": "2",
"col_1": "A",
"col_2": "B",
"col_3": "C"
},
...
...
...
{
"id": "100",
"col_1": "A",
"col_2": "B",
"col_3": "C"
}
]
有一件事是行不通的,那就是建立一个庞大的列表,然后把它分成n个大小为100的列表。原因是我的机器不能在任何给定的时间都在内存中保存所有的数据。
可以通过使用range(100)
和except StopIteration:
来做到这一点,但它不是很漂亮。相反,生成器非常适合一次从CSV文件中获取100行数据块。由于它不会使实际的迭代和请求逻辑混乱,因此可以编写相当优雅的代码。检查:
import csv
import requests
from itertools import islice
def chunks(iterator, size):
iterator = iter(iterator)
chunk = tuple(islice(iterator, size))
while chunk:
yield chunk
chunk = tuple(islice(iterator, size))
with open('csv.csv', 'rU') as f:
reader = csv.reader(f, skipinitialspace=True)
header = next(reader)
for rows in chunks(reader, 100):
rows = [dict(zip(header, map(str, row))) for row in rows]
r = requests.post(url, headers=i_headers, json=rows)
print str(reader.line_num) + "-" + str(r)
我不完全确定你从哪里得到i_headers
,但是,但我假设你已经在你的实际代码中弄清楚了。
你可以创建一个请求列表,当它的大小足够大时,将它发送到API:
import csv
import requests
with open('csv.csv', 'rU') as f:
reader = csv.reader(f, skipinitialspace=True)
header = next(reader)
requestList = []
for row in reader:
requestList.append(dict(zip(header, map(str, row))))
if len(requestList) >= 100:
r = requests.post(url, headers = i_headers, json = requestList)
print str(reader.line_num) + "-" + str(r)
requestList = []
然后,您只需要注意,您还为最后一个非完整列表调用API。可以通过在循环后调用带有剩余列表的API来完成,或者CSV阅读器可以告诉您它是否是最后一行。