Adding more Exceptions

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
nelfata
Posts: 74
Joined: Wed Apr 30, 2014 10:50 pm

Adding more Exceptions

Post by nelfata » Tue Jun 24, 2014 8:58 am

What would be the best method to add more exceptions?
- extend the built-in exceptions?
- is there another user extension to add more exceptions

Some examples:
timeout, no data, read error,...

Thanks.

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: Adding more Exceptions

Post by pfalcon » Tue Jun 24, 2014 2:15 pm

https://docs.python.org/3.4/tutorial/er ... exceptions

If you have issues with subclassing exceptions (or other builtin types) in MicroPython, please submit bug describing your use case and providing test case to reproduce your issue.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Adding more Exceptions

Post by dhylands » Tue Jun 24, 2014 2:46 pm

I'm assuming that you're talking about adding Exceptions from python, and not from C?

As pfalcon suggests, it should be the standard way that python supports extensions.

I threw together a small example to confirm that they work. I created a file called extest.py:

Code: Select all

class MyError(Exception):
    pass

def func1():
    print("About to throw MyError")
    raise MyError
    print("After raising MyError")

def func2():
    try:
        func1()
    except MyError:
        print("Whoops")
and this is what I got on the pyboard:

Code: Select all

Micro Python v1.1.1-32-gcd590cb on 2014-06-24; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import extest
>>> extest.func2()
About to throw MyError
Whoops

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Adding more Exceptions

Post by dhylands » Tue Jun 24, 2014 5:17 pm

I added some arguments to MyError.

I also discovered that currently the only way to get a traceback printed is to pass the exception out to the REPL. There doesn't seem to be any way for the python code to print a traceback and retain control.

Updated example:

Code: Select all

class MyError(Exception):
    pass

def func1():
    print("About to throw MyError")
    raise MyError("some args", 57)
    print("After raising MyError")

def func2():
    try:
        func1()
    except MyError as ex:
        print("Whoops")
        raise ex

func2()
Results of running unix version:

Code: Select all

 >./micropython ../../extest.py 
About to throw MyError
Whoops
Traceback (most recent call last):
  File "../../extest.py", line 16, in <module>
  File "../../extest.py", line 14, in func2
  File "../../extest.py", line 14, in func2
  File "../../extest.py", line 11, in func2
  File "../../extest.py", line 6, in func1
MyError: ('some args', 57)
The results running on pyboard are similar, except the fiename is slightly different.

nelfata
Posts: 74
Joined: Wed Apr 30, 2014 10:50 pm

Re: Adding more Exceptions

Post by nelfata » Tue Jun 24, 2014 6:05 pm

Thank you for the prompt reply.
In fact I was talking about a C exception to be raised from C and caught in MP. I made the modifications in the C firmware, but I was wondering if there is some simpler way to extend the exception (in C) set without modifying the core MP code.

By the way since you mentioned about the trace, I noticed that if exceptions occur from other lower level C code layers, and in the Python code a Try/Exception is added, then the lower level exception messages are hidden and it becomes very hard to know what occurred.

nelfata
Posts: 74
Joined: Wed Apr 30, 2014 10:50 pm

Re: Adding more Exceptions

Post by nelfata » Tue Jun 24, 2014 7:20 pm

To add to this note, if there is a print in the C code and a Try/Except is added on the Python side, the print in C seems to be masked.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Adding more Exceptions

Post by dhylands » Tue Jun 24, 2014 7:31 pm

Exceptions at the C level are really setjmp/longjmp (or conceptually similar).

In C you raise an exception using nlr_raise: like so:
https://github.com/micropython/micropyt ... int.c#L143

To add a custom exception in C, you can just create an your exception as an object derived from Exception.

Right now it looks like MP_DEFINE_EXCEPTION is in objexcept.c and it sounds like it should be moved into a header so that C modules could create their own exceptions. It also looks like some of the required support functions are declared static, and they should probably be exposed.

For an example of catching an exception in C, you can look at:
https://github.com/micropython/micropyt ... int.c#L367

Can you give an example of the hidden try/catch block thing in python? I'm guessing that it can be recoded, but without knowing what your python code looks like it's hard to know if it's a real problem (i.e. bug) or not (i.e. can be recoded).

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Adding more Exceptions

Post by dhylands » Tue Jun 24, 2014 7:38 pm

nelfata wrote:To add to this note, if there is a print in the C code and a Try/Except is added on the Python side, the print in C seems to be masked.
I think we'd need to see an example. The print should be happening right when the print statement is called. I'm not aware of any way to mask the print. The only thing I can think of is that it's sitting in the buffer to be sent out over USB serial, and that never happens because something resets USB. In this case if you set things up so that prints go out a UART, you should definitely see the print exactly when it occurs (there is no buffering of any kind which gets in the way of UART prints)

nelfata
Posts: 74
Joined: Wed Apr 30, 2014 10:50 pm

Re: Adding more Exceptions

Post by nelfata » Tue Jun 24, 2014 8:30 pm

Here is an example where the print in C is being masked when using a try/except block in MP:
(the Wiki is changing the tabs)

MP CODE
-----------
while receiveComplete == False:
try:
d = self.client_s.read(size, flags, timeout_ms*10)
except NoDataError:
print('no data error in read')
continue
except:
# some error occurred, we may need to restart the connection
self.errorFlag = 1
print('error in read')
break

C CODE
---------
... some code
status = _sock_isavailable(self->fd, 1, timeout);
RAISE_EXCEP(status>=0, mp_type_ReadError, "read failed");
RAISE_EXCEP(status==0, mp_type_NoDataError, "no data"); <<<<------MP is detecting this exception (exception message is masked)
....

STATIC int _sock_isavailable(int fd, int r_or_w, int timeout_ms)
{
...some code...
rc = cc3k_sock_select(fd+1, fd_read, fd_write, NULL, ptimeout);
if(rc == 0)
{ // select timed out, no data available
printf("select timedout\n"); <<<<<-------MP is masking this printf
}


NOTE: I created new exceptions here ReadError and NoDataError.

#define RAISE_EXCEP(assertion, type, msg) { if ((assertion) == 0) nlr_raise(mp_obj_new_exception_msg(&(type), (msg))); }

nelfata
Posts: 74
Joined: Wed Apr 30, 2014 10:50 pm

Re: Adding more Exceptions

Post by nelfata » Tue Jun 24, 2014 8:34 pm

dhylands wrote:
nelfata wrote:To add to this note, if there is a print in the C code and a Try/Except is added on the Python side, the print in C seems to be masked.
I think we'd need to see an example. The print should be happening right when the print statement is called. I'm not aware of any way to mask the print. The only thing I can think of is that it's sitting in the buffer to be sent out over USB serial, and that never happens because something resets USB. In this case if you set things up so that prints go out a UART, you should definitely see the print exactly when it occurs (there is no buffering of any kind which gets in the way of UART prints)
Could it be that we need to flush the printf (fflush(stdout)) when using the USB serial?

Post Reply