pyserial and threads

Chris Angelico rosuav at gmail.com
Thu Sep 17 09:45:58 EDT 2015


On Thu, Sep 17, 2015 at 11:26 PM, pozz <pozzugno at gmail.com> wrote:
> How to have a non-blocking write?
>
> Maybe the problem happens when port 1 thread is in .read() (it blocks for 1
> second) and port 2 thread tries to write one byte (that was just received)
> to port 1.

I'm not sure, as I've never worked with serial ports in this way. What
you'd want is some form of call that says "write these bytes if you
can, but don't if you can't, and just tell me how many you wrote". A
quick look at the pyserial docs suggests that you may be able to
accomplish this by opening the port with writeTimeout=0, or possibly
some other value (it'll wait that many seconds - float allowed -
before giving up).

If it returns 0, stating that the byte wasn't written, you'd need to
hang onto that byte until it can write successfully. I've no idea how
you'd go about knowing that. With TCP sockets, select.select() is your
friend; if you're really lucky, pyserial will work with the same kind
of structure.

>> Where's the code getting blocked?
>
> I don't knwo exactly. I can only see no more bytes are received on COM
> ports.

Here's a way to test: Bracket each potentially-blocking call with a
status update, and then have your main loop collect the statuses and
print them out. Something like this:

  def reader(self):
    try:
      while self.alive and self._reader_alive:
        self.status = 'R' # Reading
        data = self.serial.read(1)
        self.status = 'P' # Processing
        if len(data) > 0:
          for n,p in enumerate(self.com_list):
            if p[1] != self:
              self.status = n # Writing to port n
              p[1].write(data)
              self.status = 'P'
    except serial.SerialException:
      # This looks like a job for try/finally, actually
      self.status = 'Z' # Dead
      self.alive = False
      raise

Then your main thread, instead of just sleeping forever, does this:

    while True:
      time.sleep(1)
      print(" ".join(port.status for port in ports), end="\r", flush=True)

You should normally see most of the threads blocked on reading,
assuming that the traffic levels are lower than the ports' capacities.
If you start seeing them blocked on writing, chances are they'll all
be blocking on the same port, and that's the port that's holding you
up.

Caution: Code utterly untested. You may have to debug some stuff.

ChrisA



More information about the Python-list mailing list