1

I can't figure out how to make this small http server reply the get request and play a sound in parallel.

Current code, does not close the get request until the sound "winsound.PlaySound("SystemExit", winsound.SND_ALIAS)" end playing.

What i need is for the sound to be async to the request so that the get request ends asap and the sound keeps playing.

#!/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()
Bharel
  • 23,672
  • 5
  • 40
  • 80
Uniextra
  • 133
  • 3
  • 17

2 Answers2

1

BACKGROUND

So basically, it's question about execution scope in Python. Back to your code above, in order for request to finish it has to be execute all task.

  • send response (this one doesn't make effect, because you have to return result from the method get)
  • setting headers
  • playing music

Obviously, you return at the end of the request execution and your thread monitor just one. So request will finish after finishing all the tasks.

SOLUTION

So as you mentioned in the question, you are right. To play music on your Server on the request, you have to run async task and let you request return result from get request. For ex. by using asyncio (it's very handy lib, so check it out)

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()
GensaGames
  • 5,538
  • 4
  • 24
  • 53
1

Use a flag to run it async:

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

If you wish to have tighter control, use concurrent.futures.ThreadPoolExecutor() to run it in a different thread:

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))
Bharel
  • 23,672
  • 5
  • 40
  • 80