RPi script to periodically collect data from Arduino through serial port
A simple technique to avoid busy wait is to

import select
....
select.select([], [], [], timeout)


The timeout is simply target_time - current_time in seconds. Since select interprets it as a floating point, the granularity is in  milliseconds at least.

I see no possibility for time drift.
The nested loops in read_data do not look right. Consider instead

def read_data():
    data = []

    temp = None
    while temp != '*':
        temp = arduino.read()...

    while temp != '#':
        temp = arduino.read()...
        data.append(temp)

    return data[:-1]

I am not sure why do you sleep() before reading the response.