Вопрос или проблема
Мне нужна функция, которая будет запускаться в конце другой функции неблокирующим образом. Для этого я использую потоки (и ответ здесь: https://stackoverflow.com/a/6683797/4552286).
import threading
def checkValidQRCode(qrcode):
url=""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json" # Указываем тип содержимого как JSON
}
response = requests.get(url, headers=headers)
# Проверяем код состояния ответа
if response.status_code == 200:
# Парсинг JSON ответа
json = response.json()
print(json)
if len(json) > 0:
print("открыть дверь по проверке валидного QR-кода")
if(json[0]["Static"]==False): # нестатичный код, должен быть помечен как использованный
# запускаем обновление доступа в отдельном потоке
thread = threading.Thread(target=updateAccessCodeToSpent, args=(json[0]["Id"],))
thread.start()
return "unlock"
def updateAccessCodeToSpent(id):
time.sleep(5)
while(True):
if someCondition == True:
checkValidQRCode("qrcode")
print("это код сразу после checkValidQRCode() в цикле")
Я хочу, чтобы оператор print после триггера в цикле выполнялся сразу после завершения обработки запроса. Он ожидает 5 секунд перед печатью. Кроме того, я знаю, что это время связано с обновлением доступа, так как когда я закомментирую time.sleep, код после триггера выполняется немедленно.
Ответ или решение
Проблема, с которой вы столкнулись, заключается в том, что функция checkValidQRCode
, несмотря на использование потоков, блокирует выполнение последующих строк кода в основном потоке до тех пор, пока не завершится запрос requests.get()
и последующие операции. Давайте разберем, как правильно запустить функцию updateAccessCodeToSpent
в неблокирующем режиме и вернуть управление в основной поток сразу после обработки QR-кода.
Вот исправленная версия вашего кода:
import threading
import requests
import time
def checkValidQRCode(qrcode):
url = ""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json" # Укажите тип содержимого как JSON
}
response = requests.get(url, headers=headers)
# Проверяем код состояния ответа
if response.status_code == 200:
# Парсим JSON-ответ
json = response.json()
print(json)
if len(json) > 0:
print("unlock door from check valid qr code")
if json[0]["Static"] == False: # Нестатичный код, следует отметить как использованный
# Запускаем updateAccessCodeToSpent в отдельном потоке
thread = threading.Thread(target=updateAccessCodeToSpent, args=(json[0]["Id"],))
thread.start() # Это не блокирует основной поток
return "unlock"
def updateAccessCodeToSpent(id):
time.sleep(5)
print(f"Access code {id} marked as spent.")
while True:
if someCondition == True:
checkValidQRCode("qrcode")
print("this is code right after checkValidQRCode() in the loop")
Основные изменения в коде:
-
Использование аргументов для потоков: Ваша строка
args=(json[0]["Id"])
была некорректной. Для передачи единственного аргумента вargs
необходимо упаковать его в кортеж, добавив запятую:args=(json[0]["Id"],)
. - Блокировка в основном потоке: Ваш запрос
requests.get()
выполняется в основном потоке, и на этом этапе выполнение заблокировано до получения ответа. Чтобы добиться неблокирующего поведения, вы можете создать отдельный поток для выполнения этого запроса или воспользоваться асинхронным программированием, например, библиотекойasyncio
и ее компонентами для работы с асинхронными HTTP-запросами, такими какaiohttp
.
Пример с использованием threading
:
Если вы хотите оставить текущую структуру кода, но позаботиться о том, чтобы HTTP-запросы также выполнялись в фоновом режиме, вы могли бы организовать его так:
def checkValidQRCode(qrcode):
thread = threading.Thread(target=processQRCode, args=(qrcode,))
thread.start()
def processQRCode(qrcode):
url = ""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
json = response.json()
print(json)
if len(json) > 0:
print("unlock door from check valid qr code")
if json[0]["Static"] == False:
threading.Thread(target=updateAccessCodeToSpent, args=(json[0]["Id"],)).start()
return "unlock"
Используя этот подход, вы создаете отдельный поток для выполнения всей логики обработки QR-кода, так что основной поток не блокируется, даже если запрашивается HTTP-ресурс.
Заключение
В случае, если вы часто работаете с параллельными задачами или асинхронным кодом, вам может быть полезно рассмотреть использование более современных инструментов и библиотек, таких как asyncio
, чтобы улучшить производительность и читабельность вашего кода.