Немедленная запись ответа JSON API в файл с запросами Python

#python #json #python-requests #stdout

#python #json #python-запросы #стандартный вывод

Вопрос:

Я пытаюсь извлечь данные из API и немедленно записать ответ JSON непосредственно в файл, а не сохранять какую-либо часть ответа в памяти. Причина этого требования заключается в том, что я выполняю этот скрипт на AWS Linux EC2, который имеет только 2 ГБ памяти, и если я попытаюсь сохранить все в памяти, а затем записать ответы в файл, процесс завершится с ошибкой из-за нехватки памяти.

Я пытался использовать f.write() , а также sys.stdout.write() , но оба этих подхода, казалось, записывали файл только после выполнения всех запросов. Хотя это сработало с моим небольшим примером, это не сработало при работе с моими фактическими данными.

Проблема с обоими приведенными ниже подходами заключается в том, что файл не заполняется до завершения цикла. Это не будет работать с моим фактическим процессом, поскольку на компьютере недостаточно памяти для хранения всех ответов в памяти.

Как я могу адаптировать любой из приведенных ниже подходов или придумать что-то новое, чтобы немедленно записывать данные, полученные от API, в файл, не сохраняя ничего в памяти?

Примечание: я использую Python 3.7, но с удовольствием обновлю, если есть что-то, что упростит это.

Мой подход 1

 # script1.py
import requests
import json

with open('data.json', 'w') as f:
    for i in range(0, 100):
        r = requests.get("https://httpbin.org/uuid")
        data = r.json()
        f.write(json.dumps(data)   "n")
f.close()
  

Мой подход 2

 # script2.py
import request
import json
import sys

for i in range(0, 100):
    r = requests.get("https://httpbin.org/uuid")
    data = r.json()
    sys.stdout.write(json.dumps(data))
    sys.stdout.write("n")
  

При подходе 2 я попытался использовать > для перенаправления вывода в файл:

 script2.py > data.json
  

Ответ №1:

Вы можете использовать response.iter_content для загрузки содержимого порциями. Например:

 import requests


url = 'https://httpbin.org/uuid'

with requests.get(url, stream=True) as r:
    r.raise_for_status()
    with open('data.json', 'wb') as f_out:
        for chunk in r.iter_content(chunk_size=8192): 
            f_out.write(chunk)
  

Сохранение data.json с содержимым:

 {
  "uuid": "991a5843-35ca-47b3-81d3-258a6d4ce582"
}