Асинхронная обработка данных в блоке tkinter — несколько циклов

#python #pandas #multithreading #asynchronous #tkinter

Вопрос:

У меня есть базовое оконное приложение, использующее класс приложений tkinter (приложение класса(tk.Tk)). База кода для запуска запуска имеет следующий код:

 loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
app = App(loop)
loop.run_forever()
 

Часть инициализации приложения содержит следующее, которая содержит задачу создания цикла для функции обновления:

 def __init__(self, loop, interval=0.05):
        super().__init__()
        self.loop = loop
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.update_task = loop.create_task(self.updater(interval))
 

Функция обновления:

 async def updater(self, interval):
        while True:
            self.update()
            await asyncio.sleep(interval)
 

Кнопка запускает соединение в другом файле, который занимается получением и обработкой данных websocket. После нескольких итераций, опробовав разные способы, я остановился на потоковой передаче, которая, похоже, работает быстрее всего.
ОБНОВЛЕНИЕ: удалена потоковая обработка, поскольку она использовалась неправильно, тот же результат, что и при простом вызове функции.

 def start_connection():
    data_connection.main()
 

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

 sem = asyncio.Semaphore(1000)
async def stream_loop():
      async with sem: 
         asyncio.ensure_future(stream_loop())
         await stream_process()
    
asyncio.ensure_future(stream_loop())
 

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

  async def recalculate_loop():
        async def refresh():
            await recalculate_market_stats()
            await asyncio.sleep(1)
            await refresh()
        await refresh()
 asyncio.ensure_future(recalculate_loop())
 

Есть ли способ запустить эти несколько процессов асинхронно и параллельно, используя несколько ядер в процессоре? Или это уже происходит так быстро, как только возможно в задней части, и не имеет никакого значения?

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

1. Я думаю, что у вас есть самая распространенная ошибка — target= нужно имя функции без () — так называемой callback — и позже она будет использоваться () для ее запуска в отдельном потоке.

2. @furas — я удалил протекторную часть кода, просто инициируйте соединение с помощью data_connection.main().