Code:
import serial

import time

import atexit



class SerialReader:

    def __init__(self, port='COM3', baud_rate=9600, timeout=1):

        self.ser = serial.Serial(port, baud_rate, timeout=timeout)

        atexit.register(self.close)  # Register the close method to be called on exit



    def read_serial_data(self, num_readings=10):

        readings = []

        for _ in range(num_readings):

            if self.ser.in_waiting > 0:

                line = self.ser.readline().decode('utf-8').rstrip()

                readings.append(line)

                print(line)

            time.sleep(1)  # Delay between readings

        return readings



    def close(self):

        self.ser.close()



# Example usage

if __name__ == '__main__':

    reader = SerialReader()

    data = reader.read_serial_data()


that's the laptop side code.

the nice thing about atexit is, it will handle all the wrap up, needed to be done when the program closes.

and as you can see you set it whenever (the c'tor in this case), instead of the end of the program.