Python Forum

Full Version: waiting for barcode scanner output, while main program continues to run
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I am trying to accomplish the following situation.
I have a barcodescanner connected by USB to a raspberry pi 4 and I am able to capture the output of the barcode scanner.
How I would like to have the program behave is: the scanner should wait for a barcode that gets scanned, while the main program continues to run and performs other tasks.
My thoughts were to use threading for this, but when I run the code below, the main program is also waiting for the input from the scanner. I think I am missing something, but I can't figure out how to do this.
I hope somebody can help me or guide me in the right direction.

import threading
import serial
import queue

q = queue.Queue()
ser = serial.Serial("/dev/ttyACM0",9600)

def thread_scanner(q):
    try:
        ser.open()
    except IOError:
        ser.close()
        ser.open()

    barcode = ser.readline()
    q.put(barcode)

if __name__ == "__main__":
    scanner_thread = threading.Thread(target=thread_scanner, args=(q,))
    scanner_thread.start()    

    while True:

        if q.qsize > 0:
            barcode = q.get()
            q.task_done()
            print(barcode)
            barcode = ""
        else:
            print("1")
        
        scanner_thread.join()
Thank you in advance.
I haven't run the code. If you do not need access to thread and q from other functions, you can creates them inside a function.
I think your problem comes from scanner_thread.join() inside the loop. This blocks your code until the thread ends, but the thread does never end.

import threading
import serial
import queue


def thread_scanner(q):
    # serial.Serial should support context managers
    with serial.Serial("/dev/ttyACM0", 9600) as ser:
        while True:
            barcode = ser.readline()
            q.put(barcode)


def mainloop():
    """
    Starts the mainloop to print barcodes
    
    Everything else must be done inside this function or
    you put it on module level, if it's required.
    """
    q = queue.Queue()
    scanner_thread = threading.Thread(target=thread_scanner, args=(q,))
    scanner_thread.start()
    while True:
        barcode = q.get() # get blocks until it has an element available
        q.task_done()
        print(barcode)


if __name__ == "__main__":
    mainloop()
Since Python 3 serial.read* return bytes. You can decode them, if it's ASCII or some other kind of encoding.
If it's binary data, you've to convert it into data you can work with.
Hi Dead_Eye,

Thank you for your answer.
I will run the code you have suggested.
For the moment I have fixed it by using the asyncio and serial_asyncio libraries.

Kind regards,
lightframe109
In many cases, asyncio is better than threads. Specially if it's IO related.

Actually, the state of the implementation of async pyserial is experimental.
Quote:Warning

This implementation is currently in an experimental state. Use at your own risk.

Just a warning, if something does not work, then expect also bugs from PySerial.