1

I am trying to write a small Python script to read data from a serial port and simply display it to the screen. It seems to be working, but there seems to be a delay to when I see data displayed on the screen.

import serial
import sys

SerialGF = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity='N', stopbits=1, xonxoff=0, rtscts=0, timeout=0)

def main():
    # openSerial_GF()
    print SerialGF.isOpen()
    SerialGF.flush()
    SerialGF.flushInput()
    SerialGF.flushOutput()
    try:
        while True:
            readSerial_GF()
    except KeyboardInterrupt:
        pass
    SerialGF.close()
    print SerialGF.isOpen()

# def openSerial_GF():
#     global SerialGF = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity='N', stopbits=1, xonxoff=0, rtscts=0, timeout=0)

def readSerial_GF():
    s = SerialGF.read(SerialGF.inWaiting())
    sys.stdout.write(s)

if __name__ == "__main__":
    main()

The data on serial port is a stream of dash characters, '-', until some event occurs. What I am seeing a delay when the data is displayed to the screen. What is odd is that 1024 characters are displayed at a time. I have set the timeout to zero (0) so it should return straight away, but it isn't. Does anyone have any ideas why there is a delay?

Thanks, Mark

lordhog
  • 3,427
  • 5
  • 32
  • 43
  • 1
    Maybe related to buffering that is turned on by default in `sys.stdout`. Can you run in unbuffered mode `python -u` to see if the problem persists? [Here](http://stackoverflow.com/questions/107705/python-output-buffering)'s another question which digs into the buffering aspect. – vikramls Nov 18 '14 at 00:25
  • 1
    Or just do a `sys.stdout.flush()` after the `write`. The buffering is explained in the [`open`](https://docs.python.org/2/library/functions.html#open) docs (not the specific details on how `sys.stdout` is opened, which obviously happens before you even get control). On many systems, the "system default" is to buffer until either a newline is printed or some max line length (like 1024) is reached, which seems like exactly what you're seeing. – abarnert Nov 18 '14 at 00:36

1 Answers1

3

This is almost certainly a buffering issue. The short answer is, if you want output to show up immediately, do sys.stdout.flush() after each sys.stdout.write(…).

On most platforms, by default,* the stdio streams end up line buffered. This means that anything written is buffered up until you either write a newline, or fill up the buffer inside stdio, which is usually some nice round length like 1024 bytes.

Python 2.x** mostly leaves buffering up to the C stdio library, so for full details, you want to look up your platform's fopen and possibly fwrite implementations. The docs for open explain the options Python gives you for controlling the buffering, and the command line and environment docs explain how you can influence the way the stdio streams are opened. But really, rather than forcing everyone to run your program with -u, it's better to just explicitly flush when you want to make sure output appears.

* If you open the files in binary mode—which is what -u and PYTHONUNBUFFERED control—you get unbuffered output. If you open the files in text mode and isatty() is true or not available, you usually get line-buffered mode. Otherwise, you usually get "fully-buffered" mode, meaning there's a fixed-size buffer and writes happen when that buffer is filled.

** Note that this is all Python 2.x-specific; 3.x has its own file objects that work directly on top of native file descriptors/handles, instead of using C stdio.

abarnert
  • 354,177
  • 51
  • 601
  • 671