Path: csiph.com!eternal-september.org!feeder.eternal-september.org!border1.nntp.ams1.giganews.com!border2.nntp.ams1.giganews.com!nntp.giganews.com!newsfeed.xs4all.nl!newsfeed7.news.xs4all.nl!nzpost1.xs4all.net!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'debug': 0.04; 'float': 0.05; 'tries': 0.05; 'cc:addr:python-list': 0.09; 'blocked': 0.09; 'non-blocking': 0.09; 'port,': 0.09; 'stating': 0.09; 'thread': 0.10; 'def': 0.13; 'thu,': 0.15; '"write': 0.16; "'r'": 0.16; 'bracket': 0.16; 'caution:': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'len(data)': 0.16; 'received)': 0.16; 'self.status': 0.16; 'statuses': 0.16; 'structure.': 0.16; 'stuff.': 0.16; 'subject:threads': 0.16; 'tcp': 0.16; 'threads': 0.16; 'true:': 0.16; 'utterly': 0.16; "where's": 0.16; 'wrote:': 0.16; 'byte': 0.18; 'bytes': 0.18; 'try:': 0.18; 'written,': 0.18; '2015': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'assuming': 0.22; 'sep': 0.22; 'this:': 0.23; 'header:In-Reply- To:1': 0.24; "i've": 0.25; 'message-id:@mail.gmail.com': 0.27; 'idea': 0.28; 'looks': 0.29; '(it': 0.29; 'blocking': 0.29; 'sure,': 0.29; "they'll": 0.29; 'thread,': 0.29; 'raise': 0.29; "i'm": 0.30; 'print': 0.30; 'that.': 0.30; 'code': 0.30; 'normally': 0.30; 'seconds': 0.31; 'up.': 0.32; 'says': 0.32; 'possibly': 0.32; 'maybe': 0.33; 'getting': 0.33; 'problem': 0.33; 'except': 0.34; 'worked': 0.34; 'received:google.com': 0.35; 'false': 0.35; 'something': 0.35; 'but': 0.36; 'should': 0.36; 'instead': 0.36; "wasn't": 0.36; 'pm,': 0.36; 'subject:: ': 0.37; 'really': 0.37; 'skip:p 20': 0.38; 'data': 0.39; 'does': 0.39; 'skip:e 20': 0.39; 'some': 0.40; 'hang': 0.60; 'your': 0.60; '(that': 0.63; 'more': 0.63; 'levels': 0.70; 'serial': 0.70; 'chrisa': 0.84; 'ports.': 0.84; 'reading,': 0.84; 'to:none': 0.91; 'writing,': 0.91; 'ports': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=6N2wpT1I4W+pWwUGOHfwKKO/eRB0Znfdlx3Z3SCy7rA=; b=Zhw3tsz4icKVDNOXgJbvKJCE5KxRIBlpgJedhW5qN/E9i4wwTN9DPCqihcfYjVXqkD ddjhx/88SY/2se+hOWAscCjb7/ryB0gYIIIPlhbKilbgdxRJREXl/CoyuCIPNwcUhRSN dWmZUMYPsd8jtDOjY5GvOGVq2h36CK9Y4gVep9q0zTiPEVXAwq+oAvNgzMwUx46qdEU4 8JJFrlSicDdFV0v1qKsJECKvdEK45YncLzvoOej0TApBBsiPxE9G2AAHvsU3FU3f0h4E y1CH+PRVquXz2DoWlS4JwRF4j+Opwjo6yCRtUuomevAHuVidnndxFm8JodTnMj131tVW pGVw== MIME-Version: 1.0 X-Received: by 10.107.33.81 with SMTP id h78mr5979026ioh.19.1442497558269; Thu, 17 Sep 2015 06:45:58 -0700 (PDT) In-Reply-To: References: Date: Thu, 17 Sep 2015 23:45:58 +1000 Subject: Re: pyserial and threads From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 63 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1442497560 news.xs4all.nl 23728 [2001:888:2000:d::a6]:39266 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:96770 On Thu, Sep 17, 2015 at 11:26 PM, pozz 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