3

I am trying to implement serial communication, following this advice.

Basically I will have a separate thread, that blocks, listening to the port, and when a complete line is received, push it to a global queue.

However, this warning in the documentation is confusing to me:

readlines() only works with a timeout

What does it mean? How do I implement what I intend. I would hate to have to

while True:
    a = self.ser.read(1)
    if a == '/n':
        blqblq()
    elif a == '/r'
        b = self.ser.read(1)
        if b == '/n':
            nana()
Community
  • 1
  • 1
Vorac
  • 8,726
  • 11
  • 58
  • 101

1 Answers1

4

readlines must be given a timeout because otherwise it would never finish, since there is no way to detect the end of the serial data stream (EOF).

readline blocks indefinitely when no data is being sent (or the data doesn't contain a newline), but so does your application. It's perfectly fine to write something like

def read(ser, queue):
    while True:
         queue.put(ser.readline())
threading.Thread(target=read, args=(ser, queue)).start()

or the more modern equivalent

def read(ser, queue):
    for line in ser:
         queue.put(line)
threading.Thread(target=read, args=(ser, queue)).start()

However, you should be aware that the reading thread will never finish. So if your program should ever end in a non-exceptional way (i.e. the user can somehow quit it), you need to have a mechanism to signal the reading thread to stop. To make sure that this signal is ever received, you need to use a timeout - otherwise, the thread could block indefinitely in the absence of serial data. For example, this could look like:

def read(ser, queue):
    buf = b''
    ser.timeout = 1  # 1 second. Modify according to latency requirements
    while not should_stop.is_set():
         buf += ser.readline()
         if buf.endswith('\n'):
             queue.put(line)
             buf = b''
         # else: Interrupted by timeout

should_stop = threading.Event()
threading.Thread(target=read, args=(ser, queue)).start()
# ... somewhat later
should_stop.set()  # Reading thread will exit within the next second
phihag
  • 278,196
  • 72
  • 453
  • 469
  • Thank you for the code example. But what should be added to enable host-side (not device side, but the PC the program is running on) closing of the program. I am new to threading and really don't know where to start. – Vorac Sep 11 '13 at 11:45
  • 1
    Ammended the answer - you'll want to use an [Event](http://docs.python.org/dev/library/threading.html#threading.Event). – phihag Sep 11 '13 at 12:33