Safely abortable for loop

Does there exist a safely abortable for loop?

This is relevant if I have a list of tasks I want to queue, but I don’t know how long it will take, and I don’t want to interrupt any task whilst its ongoing.

I like to queue my tasks without having to be too careful. Currently I sometimes have to deal with corrupted files because I wasn’t careful enough. (I queue them up in a for loop and use KeyBoardInterrupt to abort.)

I can probably bodge something together using Threading, but if something already exists it’s fairly likely to be of better quality.

Are tasks already enqueued? For example, if you have a while loop dequeuing tasks, do you just want to abort all enqueued ones?

I don’t really understand your question. An example of what I could do is

tasks = glob_query()
flag_file = Path("flag.txt")
flag_file.touch()
for task in tasks:
  if flag_file.exists():
    do()
    some()
    stuff()
    to(task)

(This works, in that I can abort the loop by deleting the flag file, but it has some flaws.)

As soon as I run this, I would consider all the tasks queued.

I don’t generally have a need to add tasks to the queue after the for loop has started.

I thought you were using a similar setup:

import threading
import queue

q = queue.Queue()

def worker():
    while True:
        item = q.get()
        print(f'Working on {item}')
        print(f'Finished {item}')
        q.task_done()

While task is already running?

(I’m trying to understand your situation. Some questions may seem intentionally playful, but that’s never the case.)

I’m not familiar enough with the queue or threading packages to recognise your code snippet.
I guess any actual work to be done on items in the queue will have to go where the print statements are.
How do you add tasks to the queue? When does the code start running tasks?

Yes. The current task will finish, but all tasks after will be skipped

That’s just a code sample from queue.Queue.join.


I would simply add a condition to safely break the loop once the task has finished:

condition = True

tasks = glob_query()
flag_file = Path("flag.txt")
flag_file.touch()
for task in tasks:
  if flag_file.exists():
    do()
    some()
    stuff()
    to(task)

  if not condition: break