Python thread.join (время ожидания) не истекло

#python #multithreading #python-multiprocessing #python-multithreading

#python #многопоточность #python-многопроцессорная обработка #python-многопоточность

Вопрос:

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

 def longFunc():
    # this expression could be entered by the user
    return 45 ** 10 ** 1000
 
thread = threading.Thread(target=longFunc, args=(), daemon=True)
thread.start()
thread.join(5.0)
print("end") # never reaches this point :(
 

Почему это и как я могу исправить это поведение? Должен ли я попытаться вместо этого использовать многопроцессорную обработку?

Ответ №1:

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

 def longFunc():
    while True:
        pass
 

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

Использование multiprocessing модуля, похоже, решает эту проблему:

 from multiprocessing import Process

def longFunc():
    # this expression could be entered by the user
    return 45 ** 10 ** 1000

if __name__ == "__main__":
    thread = Process(target=longFunc, args=(), daemon=True)
    thread.start()
    thread.join(5.0)
    print("end")
 

Это печатается "end" , как и ожидалось.

Комментарии:

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

2. Если вы готовы использовать многопроцессорный модуль, то это, похоже, решает проблему (я обновил свой ответ кратким примером, в остальном идентичным вашему оригиналу). Я подозреваю, что вы не найдете способа обойти это с помощью потоков Python по умолчанию, если мое предположение о взаимодействии с GIL верно.