Что вам нужно, это сбросить и восстановить все состояние генератора calcPi
.К счастью для вас все состояние указано явно в первой строке.Вот прототип, чтобы показать вам идею:
import sys
import os.path
def calcPi(state=None):
if state is None:
q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
skip_first = False
else:
q, r, t, k, n, l = state
skip_first = True
while True:
if 4 * q + r - t < n * t:
# have to skip the first yield in the "restore state" scenario because
# this is the same we returned the last time from this state
if not skip_first:
state = q, r, t, k, n, l
yield n, state
else:
skip_first = False
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
initial_state = None
total_digit_cnt = 0
buf_digit_cnt = 0
state_file_name = "piState.txt"
if os.path.isfile(state_file_name):
with open(state_file_name, "r+") as stateF:
lines = stateF.readlines()
if len(lines) > 0:
last_line = lines[-1]
# truncate the old state and save only the few last last lines
stateF.seek(0)
stateF.truncate(0)
stateF.write(lines[-3])
stateF.write(lines[-2])
stateF.write(last_line)
initial_state = map(long, last_line.replace('(', '').replace(')', '').split(','))
total_digit_cnt = initial_state[-1]
initial_state = initial_state[:-1]
if initial_state is not None:
print str((total_digit_cnt, initial_state))
pi_digits = calcPi(initial_state)
buf = ""
state_cnt = 0
with open("piDigits.txt", "a") as outF:
with open(state_file_name, "a+") as stateF:
for digit, state in pi_digits:
buf += str(digit)
buf_digit_cnt += 1
total_digit_cnt += 1
if buf_digit_cnt == 500:
print "Start dumping state %d" % state_cnt
buf_digit_cnt = 0
outF.write(buf)
buf = ""
outF.write("\n")
outF.flush()
# as states take much more space, clear old states
state_cnt += 1
if state_cnt % 50 == 0:
stateF.seek(0)
stateF.truncate(0)
stateF.write(str((state, total_digit_cnt)) + "\n")
stateF.flush()
print "End dumping state %d" % state_cnt
Идея состоит в том, чтобы возвращать не только следующую цифру, но и все состояние из генератора и периодически выгружать его в другой файл.Это всего лишь прототип.В реальном коде для обработки миллионов цифр вы, вероятно, захотите вывести состояние по времени, прошедшему с момента последнего дампа, а не по количеству, поскольку вычисление каждой следующей цифры, вероятно, будет становиться все медленнее и медленнее.Однако это усложняет код восстановления для отслеживания большего количества деталей (например, сколько цифр фактически было записано в последней строке?), Поэтому я не поместил его в PoC.