im working on a python code but im getting an error here is my code 
class Plugin:
    PIPE_PATH = "/tmp/NSLGameScanner_pipe"

    async def read_pipe(self, ws):
        if not os.path.exists(self.PIPE_PATH):
            print(f"Pipe file {self.PIPE_PATH} not found")
            return
        pipe_fd = os.open(self.PIPE_PATH, os.O_RDONLY | os.O_NONBLOCK)
        while True:
            try:
                line = os.read(pipe_fd, 1024)
            except BlockingIOError:
                await asyncio.sleep(0.1)  # No data, sleep and try again
            else:
                if line:
                    line = line.decode().strip()
                    print(f"Read from pipe: {line}")  # print to console
                    await ws.send_str(line)  # send to WebSocket client
                else:
                    break  # End of file
        os.close(pipe_fd)

    async def websocket_handler(self, request):
        ws = web.WebSocketResponse()

        logging.info(f"Preparing WebSocket with request: {request}")

        try:
            await ws.prepare(request)
        except Exception as e:
            logging.error(f"Failed to prepare WebSocket: {e}")
            raise  # Reraise the exception to handle it in the caller code

        if not os.path.exists(self.PIPE_PATH):
            logging.warning(f"Pipe file {self.PIPE_PATH} not found")
            return ws

        await self.read_pipe(ws)

        return ws

    
    
    
    
    
    # Asyncio-compatible long-running code, executed in a task when the plugin is loaded
    async def _main(self):
        decky_plugin.logger.info("Hello World!")

    async def _unload(self):
        decky_plugin.logger.info("Goodbye World!")
        if self.site:
            await self.site.stop()
            decky_plugin.logger.info("Server stopped")  # Log server stop
            await self.runner.cleanup()
            decky_plugin.logger.info("Server cleanup completed")  # Log server cleanup


    # Migrations that should be performed before entering `_main()`.
    async def _migration(self):
        decky_plugin.logger.info("Migrating")

        # Initialize the web application and set up the WebSocket route
        self.app = web.Application()
        self.app.router.add_route('GET', '/ws', self.websocket_handler)
        self.runner = web.AppRunner(self.app)
        self.site = None

        # Set the command to run your bash script
        command = "/bin/bash -c 'curl -Ls https://raw.githubusercontent.com/moraroy/NonSteamLaunchers-On-Steam-Deck/main/NonSteamLaunchers.sh | nohup /bin/bash -s -- \"Decky Plugin\"'"

        # Log the command for debugging
        decky_plugin.logger.info(f"Running command: {command}")

        # Set up the environment for the new process
        env = os.environ.copy()
        env['DISPLAY'] = ':0'
        env['XAUTHORITY'] = os.path.join(os.environ['HOME'], '.Xauthority')

        process = subprocess.Popen(command, shell=True, env=env)

        # Wait for the script to complete and get the exit code
        exit_code = process.wait()

        # Log the exit code for debugging
        decky_plugin.logger.info(f"Command exit code: {exit_code}")

        if exit_code == 0:
            decky_plugin.logger.info("Migration successful")
        else:
            decky_plugin.logger.error("Migration failed")

        # Start the web server and pipe related code here
        decky_plugin.logger.info("Hello World!")
        await self.runner.setup()
        decky_plugin.logger.info("Server setup completed")  # Log server setup
        self.site = web.TCPSite(self.runner, 'localhost', 8765)
        await self.site.start()
        decky_plugin.logger.info("Server started")  # Log server start