简体   繁体   中英

Problem with Lists and Queue.Queue Python 3

I'm working in an application where I have to receive data from a stream (Serial port) and plot it. I have two three threads, the main thread, the serial read thread and a thread that I will use to refresh the plots @ 10 to 30 hz.

Since the data is being received faster than 30hz I want to put the received data in a Queue so that when the plot refresher thread has to refresh can take all the new data and plot it.

The problem is that the data I receive, a list with ten values one for each data signal, I put it in my queue with q.put(data) but when I do a q.get() in the refresher thread, I can only read the last value i put in the queue and not the ones before.

So I simulated the incoming stream to send data every 100ms and the refresher to 1 second.

Lets say that the data I have put in is:

[1,1,1,1,1,1]
[2,2,2,2,2,2] ...
[10,10,10,10,10,10]

When I get the data in the Queue of the refreshing thread with

while not self.q.empty():
 print(q.get())

I get 10 times:

[10,10,10,10,10,10]

So is like it does save the last value but for all the put operations.

When I try with a integer instead of a list it works as expected.

I also tried encapsulating the list in a class but when I read the list inside the class I get the same result.

Example to test it:

import queue
from threading import Thread
import time


class PlotsManager(object):
    def __init__(self):
        simulator = Simulator(self)
        simulator.startSimulator()
        self.samplesQueue = queue.Queue()

        thread = Thread(target=self.plotSamples)
        thread.start()

    def putSamples(self, samples):    #Puts the samples in the queue
        print("Samples in:  {}".format(samples))
        self.samplesQueue.put(samples)

    def plotSamples(self): #Pops the samples from the queue
        while (1):
            time.sleep(1)
            while not self.samplesQueue.empty():  
                lastSamples = self.samplesQueue.get()
                print("Samples out: {}".format(lastSamples))


class Simulator():

    def __init__(self, PlotsManager):
        self.plotManager = PlotsManager

    def simulateNewData(self):
        counter = 0
        samples = [None] * 5
        while (True):
            # counter += 0.4
            counter += 1
            if counter > 100:
                counter = 0

            time.sleep(0.1)

            for i in range(5):
                samples[i] = counter
            self.plotManager.putSamples(samples)

    def startSimulator(self):
        thread = Thread(target=self.simulateNewData)
        thread.start()


if __name__ == "__main__":
    pm = PlotsManager()

Output:

Samples in:  [1, 1, 1, 1, 1]
Samples in:  [2, 2, 2, 2, 2]
Samples in:  [3, 3, 3, 3, 3]
Samples in:  [4, 4, 4, 4, 4]
Samples in:  [5, 5, 5, 5, 5]
Samples in:  [6, 6, 6, 6, 6]
Samples in:  [7, 7, 7, 7, 7]
Samples in:  [8, 8, 8, 8, 8]
Samples in:  [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples out: [9, 9, 9, 9, 9]
Samples in:  [10, 10, 10, 10, 10]
Samples out: [10, 10, 10, 10, 10]
Samples in:  [11, 11, 11, 11, 11]
Samples in:  [12, 12, 12, 12, 12]
Samples in:  [13, 13, 13, 13, 13]
Samples in:  [14, 14, 14, 14, 14]
Samples in:  [15, 15, 15, 15, 15]
Samples in:  [16, 16, 16, 16, 16]
Samples in:  [17, 17, 17, 17, 17]
Samples in:  [18, 18, 18, 18, 18]
Samples in:  [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]
Samples out: [19, 19, 19, 19, 19]

If it is changed by a number instead of a list of samples it works as expected.

well basically the solution es to use deepcopy.

putSamples(copy.deepcopy(samples))

As far as I understand this is cause by the fact that the list is passed as reference and not as value so I'm adding the same value to the queue many times. With deepcopy I'm actually copy the actual value to the queue every time I add a value to the queue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM