@billiedark said in Запускается только 140 потоков из 500:
Ресурсов ПК хватает, больше 140 не запускаются. Что можно сделать или почему так происходит?
Попробуйте запускать две копии скрипта из разных директорий
Асинхронная функция запускается из основного потока. Сам скрипт многопоточный, и в каждом потоке БАСа запускается асинхронная функция как-то так:
Main:
-- действия 1
-- async function
-- действия 2.
В режиме запуска выполняются все действия потока, но поток ждет, пока асинхронная функция не завершит работу и не запускает новый поток. Как сделать так, чтобы асинхронная функция запускалась как демон, не приводя к ожиданию ее завершения потоком, из которого она была запущена?
Вот настройки:

Можно запускать ее в onApplicationStart, но это не очень подходит.
Вы пытаетесь сделать многопоток в многопотоке ... Упростить никак ?
Задачу опишите и может подскажут ...
В скрипте нужно отменять активации номеров. Если отменить номер незадолго после взятия, то сервис СМС вернет ошибку. Поэтому я сделал функцию, которая в течение 2 минут пробует отменить номер, и вызываю ее как асинхронную функцию. Чтобы отмена номера выполнялась как фоновая задача, и основные потоки ее не ждали.
Ожидаемое поведение: поток баса вызывает функцию отмены номера и, не дожидаясь результата асинхронной функции, запускает следующее выполнение.
Как работает по факту: поток вызывает функцию асинхронно, не дожидаясь ее завершения, выполняет действия до конца. Но не запускает следующее выполнение, а ждет пока асинхронная функция завершится.
Как можно сделать:
Вызывать асинхронную функцию из onApplicationStart, брать таски на отмену из какой-нибудь очереди, вроде базы данных или глобальной переменной. Но тогда будет ряд проблем:
В общем, значительно проще запускать фоновую задачу из обычного потока, и передавать ей что нужно. Но очень странно, что поток ждет асинхронную функцию.
P.S. Написал тестовый шаблон, но он работает нормально, магия какая-то.
test_async_function.xml
Так не ждите выполнения асинхронной - там по сути просто гет запрос ... даже если в цикле ... По идеи вообще один ...
@thepappo said in Нормальное завершение потока, из которого запускается асинхронная функция:
В скрипте нужно отменять активации номеров. Если отменить номер незадолго после взятия, то сервис СМС вернет ошибку.
Я написал отдельный скрипт, который по API получает номера, которые вот-вот истекут и отменяет их. Скрипт запускается в цикле каждую минуту.
Например, номер дается на 20 минут, поток в скрипте у меня не может взять номер на это время, а может, к примеру на 5 минут максимум, значит я могу смело отменять все номера, которые были взяты более 15 минут назад.
5 минут взяты для примера. Я знаю, что я беру номер из сервиса, что-то там делаю, жду смс-ку и все это занимает у меня максимум эти самые 5 минут.
Сам скрипт ни о каких потоках, скриптах и так далее понятия не имеет и работает автономно.
import logging
import os
import datetime
import time
from dotenv import load_dotenv
from smsactivate.api import SMSActivateAPI
# Configure logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("[sms_activate]")
# Load environment variables from .env file
ABS_PATH = os.path.dirname(os.path.abspath(__file__))
load_dotenv()
def main(api_key: str, threshold_seconds: int = 15 * 60):
"""
Main function to check and process active activations.
Args:
api_key (str): API key for SMSActivate service.
threshold_seconds (int): Threshold in seconds to consider activation time.
Returns:
None
"""
sa = SMSActivateAPI(api_key)
sa.debug_mode = True
# Get active activations
activations = sa.getActiveActivations()
if activations.get("error") == 'NO_ACTIVATIONS':
logger.info("No pending activations found.")
return False
# Check if activations retrieval was successful
if activations.get("status") != 'success':
raise Exception("Activation status is not success")
# Loop through active activations
for one in activations["activeActivations"]:
if one["smsCode"]:
# Skip if activation is already used
continue
# Parse activation time
activation_time_str = one["activationTime"]
activation_time = datetime.datetime.strptime(activation_time_str, '%Y-%m-%d %H:%M:%S')
current_time = datetime.datetime.now()
# Calculate time difference in seconds
time_difference = current_time - activation_time
seconds_difference = time_difference.total_seconds()
# Log the time difference
logger.info("Seconds difference from activation time to now: %s" % seconds_difference)
# Check if activation time exceeds threshold
if seconds_difference > threshold_seconds:
logger.info("Activation time exceeds threshold for: %s" % one)
# Mark activation as used
sa.setStatus(id=one["activationId"], status=8)
if __name__ == '__main__':
# Get SMS Activate API key from environment variables
sms_activate_api_key = os.getenv("SMS_ACTIVATE_API_KEY")
if not sms_activate_api_key:
raise Exception('SMS_ACTIVATE_API_KEY environment variable not set')
sms_activate_api_key = sms_activate_api_key.strip()
time_to_sleep = 60
while True:
try:
main(api_key=sms_activate_api_key)
except Exception as e:
# Log any exceptions
logger.error(e)
# Wait for 60 seconds before checking again
logger.info(f"Sleeping for {time_to_sleep} seconds")
time.sleep(time_to_sleep)
@thepappo понял, во все просто оказывается ... Сергедрын взял и все по полочкам разложил ... Я правда его задачи до конца не понял, по какой причине поток не может взять больше чем на пять, и почему если он не дождался не может отбить что не судьба, но главное все по уму, по науке ....
@Nicolas said in Нормальное завершение потока, из которого запускается асинхронная функция:
Так не ждите выполнения асинхронной
В том и прикол, что я не жду. В предыдущем посте шаблон выложил тестовый, он нормально работает. А рабочий - нет ). Очевидно, что-то накосячил я сам.
@thepappo said in Нормальное завершение потока, из которого запускается асинхронная функция:
@sergerdn так а при чем тут питон?
Можно реализовать эту логику на каком угодно языке.
И получить тоже самое, один автономный скрипт отмены и куча скриптов на BAS, что берут номера из смс-сервиса и не имеют никакой логики отмены их. Я пишу всякие утилиты на python, ты можешь писать на чем угодно.
@thepappo said in Нормальное завершение потока, из которого запускается асинхронная функция:
@Nicolas said in Нормальное завершение потока, из которого запускается асинхронная функция:
Так не ждите выполнения асинхронной
В том и прикол, что я не жду. В предыдущем посте шаблон выложил тестовый, он нормально работает. А рабочий - нет ). Очевидно, что-то накосячил я сам.
в ошибку и на фейл внутри асинхронной ...
@sergerdn said in Нормальное завершение потока, из которого запускается асинхронная функция:
один автономный скрипт отмены и куча скриптов на BAS
Я понимаю, что можно. Я выше и про запуск демона из onApplicationStart писал. И я сам пишу на питоне ). Но в данном случае надо было именно из потока запускать таску.