Python SimpleHTTPRequestHandler для асинхронного воспроизведения звука

#python #winsound #simplehttprequesthandler

#python #winsound #simplehttprequesthandler

Вопрос:

Я не могу понять, как заставить этот маленький http-сервер отвечать на запрос get и параллельно воспроизводить звук.

Текущий код не закрывает запрос get до тех пор, пока не прозвучит звук «winsound.Воспроизведение звука («SystemExit», winsound.SND_ALIAS)» завершите воспроизведение.

Мне нужно, чтобы звук был асинхронным с запросом, чтобы запрос get завершился как можно скорее, и звук продолжал воспроизводиться.

 #!/usr/bin/env python3

from http.server import HTTPServer, SimpleHTTPRequestHandler, test
import socketserver
from urllib.parse import urlparse
from urllib.parse import parse_qs
import sys
import winsound



class MyHttpRequestHandler(SimpleHTTPRequestHandler):
    try:

        def do_GET(self):
            # Sending an '200 OK' response
            self.send_response(200)

            # Setting the header
            self.send_header("Content-type", "text/html")

            # Whenever using 'send_header', you also have to call 'end_headers'
            self.end_headers()


            html = "ok"
            # Writing the HTML contents with UTF-8
            self.wfile.write(bytes(html, "utf8"))            
            winsound.PlaySound("SystemExit", winsound.SND_ALIAS)

            return

    except Exception as e:
        print(str(e))



# Create an object of the above class
handler_object = MyHttpRequestHandler

PORT = 8000
my_server = socketserver.TCPServer(("", PORT), handler_object)

# Star the server
my_server.serve_forever()
 

Ответ №1:

Используйте флаг, чтобы запускать его асинхронно:

 winsound.PlaySound("SystemExit", winsound.SND_ALIAS|winsound.SND_ASYNC)
 

Если вы хотите иметь более жесткий контроль, используйте concurrent.futures.ThreadPoolExecutor() для запуска в другом потоке:

 from concurrent.futures import ThreadPoolExecutor
import winsound

pool = ThreadPoolExecutor()

class MyHttpRequestHandler(SimpleHTTPRequestHandler):
    try:

        def do_GET(self):
            # Sending an '200 OK' response
            self.send_response(200)

            # Setting the header
            self.send_header("Content-type", "text/html")

            # Whenever using 'send_header', you also have to call 'end_headers'
            self.end_headers()


            html = "ok"
            # Writing the HTML contents with UTF-8
            self.wfile.write(bytes(html, "utf8"))

            pool.submit(winsound.PlaySound, "SystemExit", winsound.SND_ALIAS)

            return

    except Exception as e:
        print(str(e))
 

Ответ №2:

ФОН

Итак, в основном, это вопрос о области выполнения в Python. Вернемся к вашему приведенному выше коду: для завершения запроса он должен выполнить все задачи.

  • отправить ответ (этот ответ не действует, потому что вы должны вернуть результат из метода get)
  • настройка заголовков
  • воспроизведение музыки

Очевидно, что вы возвращаетесь в конце выполнения запроса, и ваш поток отслеживает только один. Таким образом, запрос завершится после завершения всех задач.

РЕШЕНИЕ

Итак, как вы упомянули в вопросе, вы правы. Чтобы воспроизвести музыку на вашем сервере по запросу, вы должны запустить асинхронную задачу и разрешить запрашивать результат возврата из запроса get. Например, с помощью asyncio (это очень удобная библиотека, так что проверьте это)

 import asyncio
import socketserver
from http.server import SimpleHTTPRequestHandler
import winsound


class MyHttpRequestHandler(SimpleHTTPRequestHandler):
    try:

        def do_GET(self):
            self.send_response(200)
            self.wfile.write(bytes("Ok", "utf8"))

            # Shared Queue of Background Tasks
            asyncio.get_event_loop().run_until_complete(
                MyHttpRequestHandler.play_music()
            )

    except Exception as e:
        print(str(e))

    @staticmethod
    async def play_music():
        try:
            print('Playing sound!')
            winsound.PlaySound("SystemExit", winsound.SND_ALIAS)

        # Maybe you want to add Error handling
        finally:
            pass


# Create an object of the above class
handler = MyHttpRequestHandler


server = socketserver.TCPServer(
    ("", 8000), handler)


# Star the server
server.serve_forever()
 

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

1. У меня это не работает, протестировал ваш код, вставив его напрямую, и не работает

2. @user8459020 Какие-либо сбои или исключения? Или звук просто не работает.

3. @user8459020 обновленный код выше, просто небольшая опечатка