opened
kranthi-kishore
username_0
As part of script development, I have used pyserial module for accessing the DUT. I have started using inWaiting() API for reading the data displayed on DUT.

But, during some instances, I have faced the following issue while reading the data.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
   res=s.read(s.inWaiting)
  File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 468, in read
    buf = os.read(self.fd, size-len(read))
TypeError: unsupported operand type(s) for -: 'instancemethod' and 'int'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

 For some reason, inWaiting has no data and the function tries to read the difference of size and the len(read) data.
                        buf = os.read(self.fd, size-len(read))

As a work around, I have added the following snippet in serialposix.py file @ line 468.
                try:

                        buf = os.read(self.fd, size-len(read))
                except:
                        buf = os.read(self.fd, 3000)
Serial read() function throwing error when used with inWaiting() in serialposix.py
issue
created
zsquareplusc
username_1
`.inWaiting()` is a method that needs to be called to get the value, so `res=s.read(s.inWaiting)` is incorrect, missing `()` => `res=s.read(s.inWaiting())`.

in pySerial 3.x there is a new `.in_waiting` property which is read and not called, `.inWaiting()` is still available for backwards compatibility.

A note to `res=s.read(s.inWaiting())`: it may still not do what you want. If there are zero bytes ready to read, it will read the empty string. That's OK, but if you are in a loop trying to read again and again, it will lead to a high CPU load with empty reads. You could instead use `res=s.read(s.inWaiting() or 1)` which reads as much as possible but at least one byte, where it will block until one is available (and set a timeout, e.g. 3 seconds, to that it still returns from time to time, e.g. to check some application exit flag).
comment
created
cdealti
username_2
I've a related question. Very often you need to read as many bytes as are available in a blocking fashion. This allows processing the serial stream with minimum latency, for example when decoding the SLIP protocol where you need to process one byte at time but reading one byte at time from the serial port is expensive.
It can be done in different ways, for example using ```select``` or the (simplified) code below:
```
            # block until at least one byte is read or timeout
            if self.ser.timeout != timeout:
                self.ser.timeout = timeout
            self.buffer.extend(self.ser.read(1))

            # read as much as possible without blocking.
            # should we set the read timeout to 0 or call nonblocking?
            # It does not seem needed and it would use more CPU cycles
            
            # self.uart.ser.timeout = 0

            self.buffer.extend(self.ser.read(self.ser.inWaiting()))
```
This works but it would be more efficient if the API supported this read semantics.
comment
created
zsquareplusc
username_1
there is now a module implementing such a read loop: https://github.com/pyserial/pyserial/blob/master/serial/threaded/__init__.py#L140
comment
created
cdealti
username_2
Thanks, exactly what I was looking for
comment
closed
zsquareplusc
username_1
issue