@ddgryaz

Как повторно работать с pyglet, после использования многопоточности? Как завершить/очистить запущенные потоки?

Есть такой кусок кода, я использую его, чтобы выводить одновременно текст на экран и воспроизводить нужный мне .mp3 файл. В переменной introductions = строка

import time
import threading
import pyglet
from colorama import init
from colorama import Fore, Back, Style

def WelcomePrintMashin():
    for introductions in introduction:
        time.sleep(0.05)
        print(Fore.CYAN + introductions, end="", flush=True)
def WelcomMusic():
    WelcomeSong = pyglet.media.load('music/welcom11.mp3')
    WelcomeSong.play()
    pyglet.app.run()

def play1():
    while time.time() <= start_time:
        pass
    threading.Thread(target=WelcomMusic()).start()
def play2():
    while time.time() <= start_time:
        pass
    threading.Thread(target=WelcomePrintMashin()).start()
start_time=time.time()+1
threading.Thread(target=play1).start()
threading.Thread(target=play2).start()


Далее мне понадобилось еще раз воспроизвести mp3 файл, я создаю:

VorotaOpenSong = pyglet.media.load('music/vorota_open.mp3')
VorotaOpenSong.play()
pyglet.app.run()


И получаю такую ошибку:

Traceback (most recent call last):
  File "D:\PythonProject\CreateYouLife\main.py", line 114, in <module>
    pyglet.app.run()
  File "D:\PythonProject\CreateYouLife\venv\lib\site-packages\pyglet\app\__init__.py", line 107, in run
    event_loop.run()
  File "D:\PythonProject\CreateYouLife\venv\lib\site-packages\pyglet\app\base.py", line 162, in run
    platform_event_loop.start()
  File "D:\PythonProject\CreateYouLife\venv\lib\site-packages\pyglet\app\win32.py", line 89, in start
    raise RuntimeError('EventLoop.run() must be called from the same ' +
RuntimeError: EventLoop.run() must be called from the same thread that imports pyglet.app


Правильно ли я понимаю, что pyglet должен запускаться с того же потока, с которого вызывался ранее? Вопрос: как сделать чтобы работало? Я не совсем понимаю, как завершить предыдущие потоки принудительно или как переписать условие, чтобы потоки завершились и очистились сами (если это поможет мне с этой проблемой) В момент когда я вызываю VorotaOpenSong.play() мне не нужно работать с несколькими потоками, мне просто нужно вернуться в режим когда программа работала в одном потоке. Документацию по threading читал, к сожалению не смог найти ответ на свой вопрос. Спасибо!
  • Вопрос задан
  • 742 просмотра
Решения вопроса 1
@ddgryaz Автор вопроса
Я нашел решение моего вопроса, и таилось оно в самом начале. Я невероятно и злобно удивлен, что все оказалось так просто. Ведь изначально я искал, как соорудить такую конструкцию, чтобы и текст печатался и звук воспроизводился, читал про pyglet, pygame, GStreamer и кучу разных вариантов. В итоге к pyglet'у добавилось threading - многопоточность. Все сильно усложнилось, продолжая искать решение своего вопроса, а как оказалось еще и невероятное упрощение, я наткнулся на playsound.
В итоге
вместо кода который вы видите в вопросе

import time
import threading
import pyglet
from colorama import init
from colorama import Fore, Back, Style

def WelcomePrintMashin():
    for introductions in introduction:
        time.sleep(0.05)
        print(Fore.CYAN + introductions, end="", flush=True)
def WelcomMusic():
    WelcomeSong = pyglet.media.load('music/welcom11.mp3')
    WelcomeSong.play()
    pyglet.app.run()

def play1():
    while time.time() <= start_time:
        pass
    threading.Thread(target=WelcomMusic()).start()
def play2():
    while time.time() <= start_time:
        pass
    threading.Thread(target=WelcomePrintMashin()).start()
start_time=time.time()+1
threading.Thread(target=play1).start()
threading.Thread(target=play2).start()</spoiler>

я использовал playsound:
from playsound import *
import time

def MusicPrintMashin():
    playsound('D:/PythonProject/welcom.mp3', block=False)
    for introductions in introduction:
        time.sleep(0.05)
        print(introductions, end="", flush=True)

Требуется один аргумент - путь к файлу со звуком, который вы хотите воспроизвести. Это может быть локальный файл или URL-адрес.
Существует необязательный второй аргумент block, для которого по умолчанию установлено значение True. Если установить значение False, функция будет работать асинхронно.
Это мне и нужно было! В общем я еще не определился что мне делать, радоваться что я разобрался как решить мою задачу, или улыбчиво злиться, что я потратил кучу времени чтобы разобраться с многопоточностью - threading.
Надеюсь будет кому полезно!
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@agent_2203
Не работал с pyglet, но видимо тут такая же суть как и в asyncio, нужно удерживать главное событие, например в asyncio его можно менять и задавать с другого потока

asyncio.set_event_loop(asyncio.new_event_loop())
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы