Question re threading and serial i/o

Frank Millman frank at chagford.com
Tue Nov 4 10:05:38 EST 2003


Hi all

I am not sure if this question is about threading or serial i/o - it
has elements of both.

I want to capture the output from a hand-held scanner and write it to
a file. The scanner communicates with a base-station, which is
connected to the server via a serial port. The scanner is programmed
to input a code and quantity, and send the result directly to the
base-station in the form 'code' <tab> 'qty' <cr>.

Here is my first attempt - quick and dirty, but intended to prove the
concept.

#---------------------------------------------
import threading

x = 1

def main():
    global x
    print 'starting thread'
    t = threading.Thread(target=scan)
    t.start()
    while x:
        q = raw_input("Press 'q' to quit")
        if q == 'q':
            x = 0
    print 'thread finished'

def scan():
    p = file('/dev/ttyS0')
    txt = []
    while x:
        ch = p.read(1)
        if ord(ch) == 13:
            print ''.join(txt)
            txt = []
        else:
            txt.append(ch)
    p.close()
    print 'done'

if __name__ == '__main__':
    main()
#---------------------------------------------

I use threading so that the user can control the program via the
keyboard at the same time as the program is reading the serial port.
It works ok, but I do not know how to stop it cleanly. When the user
presses 'q' to quit, it sets a variable to tell the thread to
terminate, but the thread is blocked at the read statement, so it does
not know it is supposed to terminate.

I can think of two theoretical solutions, but I do not know if either
of them are possible.

1. Turn the 'read' of the serial port into a 'non-blocking' read by
checking if there are any bytes waiting to be read before actually
issuing the read statement. I have done this in other languages, but I
cannot find anything in the Python documentation that explains how to
do this.

2. Have the main thread forcibly terminate the thread doing the
reading. I cannot find anything in the Python documentation that
explains how to do this.

Any advice will be much appreciated.

Thanks

Frank Millman

P.S. I have found a way of implementing point 1 above, that seems to
work. If you don't mind, I would still like to post this, to get some
feedback about whether this is a good approach.

#---------------------------------------------
import threading, os, time

x = 1

def main():
    global x
    print 'starting thread'
    t = threading.Thread(target=scan)
    t.start()
    while x:
        q = raw_input("Press 'q' to quit")
        if q == 'q':
            x = 0
        time.sleep(0.1)
    print 'thread finished'

def scan():
    p = os.open('/dev/ttyS0',os.O_RDONLY|os.O_NONBLOCK)
    txt = []
    while x:
        try:
            ch = os.read(p,1)
            if ord(ch) == 13:
                print ''.join(txt)
                txt = []
            else:
                txt.append(ch)
        except OSError:
            time.sleep(0.1)
    os.close(p)
    print 'done'

if __name__ == '__main__':
    main()
#---------------------------------------------

Thanks

Frank




More information about the Python-list mailing list