#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 верно.