How can I trap socket errors?

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
NTL2009
Posts: 20
Joined: Wed Oct 26, 2016 10:07 pm

How can I trap socket errors?

Post by NTL2009 » Tue Nov 22, 2016 2:55 am

With help from this forum and the docs, I've come a long way in getting my little application running. So now I'm getting into the nitty-gritty of handling unexpected events, outside of my rigged test conditions.

I use the code I found here to create a socket to send/receive from a server I have running on another computer on my local network.

Code: Select all

 s = socket.socket()
 time.sleep(0.1)
 s.connect((host, port))
That code works fine, but of course I get an error if the server isn't running when I try to access it. How can I test for this and handle it 'gracefully'? In my case, I would just skip and try again an hour later, my data is stored in a file until I connect and upload it, so it's fine for me to just continue with my other operations until the socket connection is made.

I saw this socket.error statement in the docs: ( http://docs.micropython.org/en/latest/w ... ocket.html)

Exceptions --- socket.error --- socket.timeout

But I don't know how to use these in my code. Can anyone provide an example for me? I saw examples of a 'try:' and 'except socket.error, (value,message):' command, but couldn't seem to get that to work, got syntax errors at the 'except' line, and was wondering if maybe this is not yet fully implemented in MicroPython (ESP8266), or most likely a coding error on my part? I'm new to this, so examples really help.

Or some alternate to just ignore this and allow the code to return from the function?
TIA

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: How can I trap socket errors?

Post by Roberthh » Tue Nov 22, 2016 6:54 am

This piece of code does in principle what you seem to ask for;

Code: Select all

import time
import socket
s = socket.socket()
time.sleep(0.1)
try:
    s.connect(("1.2.3.4", 1234))
except Exception as err:
    print("Exception", err)
try/execpt is implemented in MicroPython, but maybe not all exception values. The link in your post points at the WiPy port, which is somewhat different to the ESP8266 port.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How can I trap socket errors?

Post by pythoncoder » Tue Nov 22, 2016 7:11 am

@NTL2009 I would study the output from your code example to see what exception is thrown. For example

Code: Select all

>>> 1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 
In that instance the exception is ZeroDivisionError. If you wanted to trap that, you would write

Code: Select all

try:
	code_which_might_fail()
except ZeroDivisionError:
	do_something_about_it()
>>> 
In general it's bad practice to write except Exception because that will trap all errors including (for example) syntax errors in your code. It's best to trap and deal with specific exceptions.
Peter Hinch
Index to my micropython libraries.

jms
Posts: 108
Joined: Thu May 05, 2016 8:29 pm
Contact:

Re: How can I trap socket errors?

Post by jms » Tue Nov 22, 2016 12:47 pm

Generally socket calls throw OSErrors or something derived from them.

As said don't catch everything or it'll include KeyboardInterrupts as well and that'll get annoying.

The other mistake is to catch exceptions and carry on silently as if everything is ok.

Jon

NTL2009
Posts: 20
Joined: Wed Oct 26, 2016 10:07 pm

Re: How can I trap socket errors?

Post by NTL2009 » Tue Nov 22, 2016 2:42 pm

Thanks so much! I will try these later today and report back.

Looks like the key is to use the "except Exception as err:" instead of my attempt with " except socket.error".

Fortunately, the way I have my app arranged, I store the events I'm monitoring in a file (ON/OFF changes in state of an appliance like a well pump, sump pump, freezer, etc), and attempt an upload each hour during the day when my computer would be on..

So if the socket isn't available, I'll just skip it until the next hour, the code is already set to handle that, I just needed a way to handle the no-connect state w/o crashing.

More later.....

NTL2009
Posts: 20
Joined: Wed Oct 26, 2016 10:07 pm

Re: How can I trap socket errors?

Post by NTL2009 » Wed Nov 23, 2016 3:24 am

OK, got a chance to add the above code sample into my code (within a function), and all works as I wanted.

Code: Select all

s = socket.socket()
time.sleep(0.1)
try:
    s.connect((host, port))
except Exception as err:
    print("Exception", err)
    return
# continue if connected
And this is the err if no server is running:
[Errno 104] ECONNRESET

Thanks - now on to tackling future memory errors. It runs fine, and I call gc.collect ever time I loop to make another check on GPIO status, and have ~ 15000 free, but it seems if I add another function it won't even load to run, just errors before running ( I assume it runs out of RAM as it tries to analyze the code). But I have more studying/experimenting to do, and will start a new thread if I have more questions.

Pretty amazing what this little board an Micropython can do!

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: How can I trap socket errors?

Post by Roberthh » Wed Nov 23, 2016 7:18 am

Hello @NTL2009,

like @jms and @pythoncoder told, it is not allways good to have an exception which catches everything, like my example. Normally the exception should be specific for the error you expect. If you do not know that beforehand, you should at least exclude keyboard interrupt, by adding a specific exception for it like:

Code: Select all

except KeyboardInterrupt:
    raise # stop in case of Ctrl.C
except Exception as err:
    # handling everything else

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: How can I trap socket errors?

Post by deshipu » Wed Nov 23, 2016 12:03 pm

"KeyboardInterrupt" is just one example of an exception you don't want to catch (another is MemoryError), but it's fine to do "except Exception:", because neither "KeyboardInterrupt", nor other such exceptions are not included in "Exception". That also means you don't need to catch and re-raise them explicitly.

User avatar
ernitron
Posts: 89
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: How can I trap socket errors?

Post by ernitron » Wed Nov 23, 2016 7:08 pm

I actually use:

Code: Select all

     socket = socket.socket()
     socket.settimeout(0.5) # otherwise it will wait forever
     socket.listen(1) # maximum number of queued connections
     while True:
         try:
            conn, addr = self.socket.accept()
         except KeyboardInterrupt:
            return
         except: # Timeout
            do_something_with_timeout_exception()
            continue
        try:
            req = conn.readline()
        except: # Timeout
            conn.close()
            return
This is because you can timeout on any socket operation.

EDITED there exist except socket.timeout

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: How can I trap socket errors?

Post by Roberthh » Wed Nov 23, 2016 8:46 pm

There seem to be no socket.timeout in the ESP8266 port.

Post Reply