Как сохранить состояние итератора в python? - PullRequest
0 голосов
/ 11 февраля 2019

У меня очень большой итератор.из-за нехватки ресурсов (сеть, память и время) я не могу выполнить свою программу за один шаг.

Поэтому я подумал, что было бы неплохо, если бы я выполнил свою программу до 10000-го элемента в итераторе изатем сохраните его состояние.в следующий раз, когда я запускаю программу, она продолжается от 10001-го элемента в итераторе.

вот код, который я использую:

import itertools
import requests

POSSIBLE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
URL = "URL?key={code}"

all_possible = itertools.combinations_with_replacement(POSSIBLE_CHARS, 29)
counter = itertools.count(start=1)

for c in all_possible:
    print("Try {}:".format(next(counter)), c)

    c_url = URL.format(code=c)
    resp = requests.get(c_url)
    if resp.status_code == 200:
        print("C found:", c)

        with open(c+".gif", 'b') as f:
            f.write(resp.content)

эта ссылка показывает, как продолжить итератор внутриодиночное исполнение.но я хочу остановить программу и выполнить снова.

1 Ответ

0 голосов
/ 11 февраля 2019

Поэтому я подумал, что было бы неплохо, если бы я запустил свою программу до 10000-го элемента в итераторе, а затем сохранил ее состояние.В следующий раз, когда я запускаю программу, она продолжается от 10001-го элемента итератора.

Вам повезло, потому что у itertools.combinations_with_replacement объектов есть API, позволяющие установить состояние.Это используется модулем copy в Python, но нет никаких причин, по которым вы также не можете подключиться.

Например, элемент 10,001 th будетбудь это:

>>> all_possible = itertools.combinations_with_replacement(POSSIBLE_CHARS, 29)
>>> for i in range(10_000): 
...     next(all_possible) 
...
>>> "".join(next(all_possible))
'aaaaaaaaaaaaaaaaaaaaaaaaaafwI'

Чтобы «перемотать вперед» к этому предмету в новом экземпляре, было бы:

>>> new_iterator = itertools.combinations_with_replacement(POSSIBLE_CHARS, 29)
>>> state = (0,)*26 + (5, 22, 33)
>>> new_iterator.__setstate__(state)
>>> "".join(next(new_iterator))
'aaaaaaaaaaaaaaaaaaaaaaaaaafwI'
>>> "".join(next(new_iterator))
'aaaaaaaaaaaaaaaaaaaaaaaaaafwJ'
>>> new_iterator.__setstate__(state)  # bonus: rewind iterator!
>>> "".join(next(new_iterator))
'aaaaaaaaaaaaaaaaaaaaaaaaaafwI'

Чтобы понять, почему комбинация 10,001 соответствует некоторому кортежудлина 29, как (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 5, 22, 33), я предлагаю вам просмотреть источники CPython , чтобы увидеть, как комбинации объектов позволяют копировать себя с сохранением состояния , а также соответствующий раздел * 1022.* docs .

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

...