The executing order gets incorrect in python threading, how to make it correct?

Solution 1:

The way you get and put data can fail if a thread takes too long "putting a record". If it takes long enough, new data will arrive and a new thread will be created and started. This thread will "put" records concurrently with the older one, resulting in out of order data.

Moreover, you are not joining the threads you create. This results in a very small resource leak (it's equivalent to not closing a file), that probably does not matter (unless you program runs continuously for many years).

The most elegant way of implementing what you need is to use a queue, as @jarmod proposed in the comments. Nevertheless, you can use a simpler approach reusing your code.

If you need the data to be processed in chunks of fixed number of records (as in you example), you can keep those chunks on a list and start a thread only after the previous one has finished:

import threading
import time

def putrecord(chunk):
    time.sleep(0.8) #it takes time to put record
    for data_put in chunk:
        print(data_put[-1])

def main():
    data=[]
    chunks = []
    sub = None
    for i in range(100):
        time.sleep(0.08) #getting data from a sensor
        data.append(i)
        if len(data) >= 10: #every 10 records
            chunks.append(data)
            data = []
            if sub and  not sub.is_alive():
                sub.join(0)
                sub = None
            if not sub:
                sub = threading.Thread(target=putrecord,args=(chunks,))
                sub.start()
                chunks = []
    if sub:
        sub.join()

if __name__ == '__main__':
    main()

If you actually don't need to process the data in chunks, you can feed whatever data you got from the sensor since the previous thread was started:

import threading
import time

def putrecord(data_put):
    time.sleep(0.8) #it takes time to put record
    print(data_put, data_put[-1]) #sometimes unordered (ex. 9,29,19,...)

def main():
    data_put=[]
    # sub = threading.Thread(target=putrecord,args=(data_put,))
    sub = None
    for i in range(100):
        time.sleep(0.01) #getting data from a sensor
        data_put.append(i)
        if len(data_put) >= 10: #every 10 records
            if sub and  not sub.is_alive():
                sub.join(0)
                sub = None
            if not sub:
                sub = threading.Thread(target=putrecord,args=(data_put,))
                sub.start()
                data_put=[]
    if sub:
        sub.join()

if __name__ == '__main__':
    main()

Please note that in both approaches you can miss the final data: you have to check if there was data waiting to be written and take care of it.