Python threading: заставить основной поток сообщать о прогрессе - PullRequest
0 голосов
/ 28 ноября 2018

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

Ниже приведена упрощенная версия того, что я придумал.Код будет запускаться test_function в 2 потоках с аргументами из input_arguments.Каждые 5 секунд будет выводиться% выполненных заданий.

import threading
import queue
import time


def test_function(x):
    time.sleep(4)
    print("Finished ", x)


num_processes = 2
input_arguments = range(10)

# Define a worker which will continuously execute function taking input parameters from the queue
def worker():
    while True:
        x = q.get()
        if x is None:
            break
        test_function(x)
        q.task_done()

# Initialize queue and the threads
q = queue.Queue()
threads = []
for i in range(num_processes):
    t = threading.Thread(target=worker)
    t.start()
    threads.append(t)

# Create a queue of input parameters for function
for item in input_arguments:
    q.put(item)

# Report progress every 5 seconds
report_progress(q)

# stop workers
for i in range(num_processes):
    q.put(None)
for t in threads:
    t.join()

Где report_progress определяется следующим образом

def report_progress(q):
    qsize_init = q.qsize()
    while not q.empty():
        time.sleep(5)
        portion_finished = 1 - q.qsize() / qsize_init
        print("run_parallel: {:.1%} jobs are finished".format(portion_finished))

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

Другая возможность состоит в определении report_progress по-другому:

def report_progress(q):
    qsize_init = q.qsize()
    time_start = time.time()
    while not q.empty():
        current_time = time.time()
        if current_time - time_start > 5:
            portion_finished = 1 - q.qsize() / qsize_init
            print("run_parallel: {:.1%} jobs are finished".format(portion_finished))
            time_start = time.time()

Я постоянно волнуюсьпроверка этого условия приведет к потере ресурсов ЦП, небольшой части, но в масштабе часов это может быть много.

Существует ли стандартный способ обработки этого?

Python: 3.6

1 Ответ

0 голосов
/ 28 ноября 2018

Пока я буду использовать простое решение, предложенное в комментариях @Andriy Maletsky.

Основной поток будет проверять каждые несколько секунд, если q еще не пусто, и выводит сообщение о прогрессе, еслис момента последнего отчета прошло более 1 часа.

time_between_reports = 3600
time_between_checks = 5
def report_progress_until_finished(q):
    qsize_init = q.qsize()
    last_report_time = time.time()
    while not q.empty():
        time_elapsed = time.time() - last_report_time
        if time_elapsed > time_between_reports:
            portion_finished = 1 - q.qsize() / qsize_init
            print("run_parallel: {:.1%} jobs are finished".format(portion_finished))
            last_report_time = time.time()
        time.sleep(time_between_checks)
...