numbers = ["https://exampkesite.com/api/info?product=2501{:0000007}".format(x)
for x in range(100000000)]
Вот эта строка одна забивает память на порядка 100000000 * 52 * 2 байт ~= 9 гигабайт (52 - длина каждого url после подстановки числа, 2 - размер каждого символа (wchar_t) в байтах). Замените списковое выражение на генератор (замените квадратные строки на круглые), чтобы адреса генерировались по мере необходимости, а не сразу все.
Также можно разбить весь объем на блоки по 10000 или 1000 адресов, отправлять запросы блоками, результаты не хранить в памяти, а сохранять сразу на диск. Либо получать, обрабатывать, и сразу сохранять, но в любом случае не хранить все промежуточные или итоговые результаты в памяти.
Оптимальный размер блоков определите экспериментально: небольшие блоки будут меньше забивать вам память, при очень маленьких блоках будет обрабатываться меньше запросов за раз, чем могло бы.
Насколько я вижу по примеру в readme репозитория grequests, это можно реализовать через grequests.imap
, что-то вроде этого:
import grequests
urls = ("https://exampkesite.com/api/info?product=2501{:07}".format(x)
for x in range(100000000))
reqs = (grequests.get(num) for url in urls)
with open("results.txt", "w") as file:
for resp in grequests.imap(reqs, size=1000):
print(resp.url, resp.text, file=file)
Я бы попробовал сначала size
вообще не ставить, потом попробовать ставить 10, 100 и выше.
grequests.imap
кстати тоже позволяет экономить память - в отличие от grequests.map
он не собирает все результаты в список (на вашей задаче он будет огромным), а возвращает их по мере получения, и вы можете их последовательно обрабатывать (или просто сохранять в файл для последующей обработки, как в моем пример).