У меня есть код Python, который выполняет дорогостоящие задания с помощью ThreadPoolExecutor, и я хотел бы отслеживать, какие из них были завершены, чтобы, если мне придется перезапустить эту систему, мне не пришлось переделывать то, что уже было выполнено. законченный. В однопоточном контексте я мог бы просто отметить то, что я сделал, на полке. Вот наивный перенос этой идеи в многопоточную среду:
from concurrent.futures import ThreadPoolExecutor
import subprocess
import shelve
def do_thing(done, x):
# Don't let the command run in the background; we want to be able to tell when it's done
_ = subprocess.check_output(["some_expensive_command", x])
done[x] = True
futs = []
with shelve.open("done") as done:
with ThreadPoolExecutor(max_workers=18) as executor:
for x in things_to_do:
if done.get(x, False):
continue
futs.append(executor.submit(do_thing, done, x))
# Can't run `done[x] = True` here--have to wait until do_thing finishes
for future in futs:
future.result()
# Don't want to wait until here to mark stuff done, as the whole system might be killed at some point
# before we get through all of things_to_do
Могу ли я уйти с этим? документация для полки не содержит никаких гарантий безопасности потоков, поэтому я думаю нет.
Итак, каков простой способ справиться с этим? Я думал, что, возможно, это поможет вставить done[x] = True
в future.add_done_callback
, но same-thread/26021772#26021772">который часто будет выполняться в том же потоке, что и будущее. Возможно, есть механизм блокировки, который прекрасно работает с ThreadPoolExecutor? Мне это кажется чище, чем написание цикла, который спит, а затем проверяет завершенные фьючерсы.