<[EMAIL PROTECTED]> wrote:
> What I actually want to do is to respond immediately if the expected > string comes in, but not raise a timeout unless it takes longer than > the maximum time. So if the device I'm communicating with usually > responds in a second, but _can_ take up to 20 seconds, I don't want to > do a sleep(20) then read the port since this will slow everything down > a lot in an average world. I want to keep checking for the expected > string, and act upon it as soon as I've got it, only raising a timeout > if I haven't got it after 20 seconds. I guess to do this using non- > blocking calls I have to do something like: > timesofar = 0 > returnstring = port.read(1) > while len(returnstring)<expectedlength: > if timesofar >= timeout: > raise SerialException('Timeout') > time.sleep(checkportinterval) > timesofar += checkpointinterval > returnstring += port.read(1) > > This seems rather messy. What I've tried this morning is to produce a > modified version of uspp with a second optional timeout parameter in > its read() function. If this is present, the timeout given is sent to > the port using SetCommTimeouts(). If it's not present, the timeouts > specified when the port was opened are sent. At first sight, with > minimal testing on Windows, this seems to be working, and will leave > my application code a lot cleaner than the non-blocking plus sleep > approach. Of course I don't know whether my method will work on Linux, > and there may be problems I haven't found yet. If it works it works - no problem with that - fight the dragons as you meet them, one at a time. I normally put something like this in a read function (from memory, not tested): error = 0 k = '' try: k = port.read(1) except IoError: error = 1 return error,k For this to work, you have to first unblock the port using fcntl: def unblock(f): """given file f sets unblock flag to true""" fcntl.fcntl(f.fileno(),f.F_SETFL, os.O_NONBLOCK) Then you put a call to the read in a loop, and use time.time() to do your time out, resetting a start_time variable at the start, and every time you get a char, and using short sleeps (millisec or so) after unsuccessful calls to make it less of a busy loop. The side benefit of this is that once you have received a char, you can change gears and use a shorter time out to detect the end of message, in a protocol and state agnostic way. - when the device has stopped sending chars for a little while it has finished saying what it wants to say. - so its easy to write a get_a_reply routine with variable time out, moving the action from the char to the message level: start_time=time.time() s = '' while time.time()-start_time < time_out: error,k = get_a_char(port) if error: time.sleep(0.001) continue s += k # keep the first char start_time = time.time() while time.time() - start_time < 0.005: # inter char time out status,k = get_a_char(port) if error: time.sleep(0.001) continue s +=k start_time = time.time() break return s # return empty string or what was received Something similar works for me on Suse Linux - not sure if fcntl works on windows. And no it isn't pretty. - but then very little of what I write is... - Hendrik -- http://mail.python.org/mailman/listinfo/python-list