【问题标题】:Python: Create equal-sized lists from an arbitrary-sized data setPython:从任意大小的数据集中创建大小相等的列表
【发布时间】:2016-11-14 23:23:15
【问题描述】:

我正在编写一个小脚本,它遍历 .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 的列表。原因是我的机器无法在任何给定时间将所有这些数据保存在内存中。

【问题讨论】:

  • 对列表进行分区

标签: python list csv dictionary


【解决方案1】:

使用range(100)except StopIteration: 可以做到这一点,但它不是很漂亮。相反,generator 非常适合一次从 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,但我假设您已经在实际代码中弄清楚了这一点。

【讨论】:

    【解决方案2】:

    您可以创建一个请求列表,只要它的大小足够大,就将其发送到 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 阅读器可以告诉您它是否是最后一行。

    【讨论】:

    • 谢谢!您可以考虑将此答案标记为您的问题的解决方案。
    猜你喜欢
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    相关资源
    最近更新 更多