Adding more Exceptions

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
dhylands
Posts: 3382
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Adding more Exceptions

Post by dhylands » Wed Jun 25, 2014 7:38 am

So I checked out master and added dh.c:

Code: Select all

#include <stdio.h>

#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"

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

STATIC int someFunc(int x)
{
    int rc = x;
    if (rc == 0) {
        printf("rc == 0\n");
    } else {
        printf("rc != 0 (%d)\n", rc);
    }
    return rc;
}

STATIC mp_obj_t dh_test(mp_obj_t x) {
  int status = someFunc(mp_obj_get_int(x));
  RAISE_EXCEP(status>=0, mp_type_IndexError, "read failed");
  RAISE_EXCEP(status==0, mp_type_IOError, "no data");
  printf("status = %d\n", status);
  return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dh_test_obj, dh_test);

STATIC const mp_map_elem_t dh_module_globals_table[] = {
    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_dh) },
    { MP_OBJ_NEW_QSTR(MP_QSTR_test), (mp_obj_t)&dh_test_obj },
};

STATIC const mp_obj_dict_t dh_module_globals = {
    .base = {&mp_type_dict},
    .map = {
        .all_keys_are_qstrs = 1,
        .table_is_fixed_array = 1,
        .used = MP_ARRAY_SIZE(dh_module_globals_table),
        .alloc = MP_ARRAY_SIZE(dh_module_globals_table),
        .table = (mp_map_elem_t*)dh_module_globals_table,
    },
};

const mp_obj_module_t dh_module = {
    .base = { &mp_type_module },
    .name = MP_QSTR_dh,
    .globals = (mp_obj_dict_t*)&dh_module_globals,
};
Added file: dhtest.py:

Code: Select all

import dh

i = 1
while True:
    print("i =", i)
    rc = i
    i -= 1
    try:
        dh.test(rc)
    except IOError:
        print('IOError: no data error in read')
        continue
    except:
        # some error occurred, we may need to restart the connection
        print('error in read')
        break
Added:

Code: Select all

    { MP_OBJ_NEW_QSTR(MP_QSTR_dh), (mp_obj_t)&dh_module }, \
into MICROPY_PORT_BUILTIN_MODULES in stmhal/mpconfigport.h (and added the appropriate extern above that)

Added:

Code: Select all

Q(dh)
Q(test)
to the end of stmhal/qstrdefsport.h

Added dh.c into stmhal/Makefile.

I get the following results:

Code: Select all

>>> import dhtest
i = 1
rc != 0 (1)
IOError: no data error in read
i = 0
rc == 0
status = 0
i = -1
rc != 0 (-1)
error in read
i.e. everything seems to be behaving as expected.

You didn't include your definitions of ReadError and NoDataError, so I used IndexError and IOError in their place.

Can you provide your definitions of mp_type_ReadError and mp_type_NoDataError?

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

Re: Adding more Exceptions

Post by nelfata » Wed Jun 25, 2014 10:47 am

Here are some more definitions:

in stmhal/mpconfigport.h
...
// NEF: exceptions...
extern const struct _mp_obj_type_t mp_type_ReadError;
extern const struct _mp_obj_type_t mp_type_NoDataError;

#define MICROPY_PORT_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, \
/* NEF: add more exceptions here...*/ \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ReadError), (mp_obj_t)&mp_type_ReadError }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_NoDataError), (mp_obj_t)&mp_type_NoDataError }

in objexcept.c
...
// NEF
MP_DEFINE_EXCEPTION(ReadError, RuntimeError)
MP_DEFINE_EXCEPTION(NoDataError, RuntimeError)

in stmhal/qstrdefport.h
...
// EXC
Q(ReadError)
Q(NoDataError)

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

Re: Adding more Exceptions

Post by nelfata » Wed Jun 25, 2014 10:51 am

I don't think I am doing anything different than what you have.
I am just using the module differently. I perform the import, instantiate the class and call the member functions.
It is confusing really.

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

Re: Adding more Exceptions

Post by dhylands » Wed Jun 25, 2014 2:29 pm

The other possibility is that something else, like a hardware interrupt is occurring and that interferes somehow.

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

Re: Adding more Exceptions

Post by nelfata » Wed Jun 25, 2014 8:49 pm

The interesting part is that if I remove the try/except block the prints show up as expected.
I will try to make a test module and give you a simple case.
Thank you for the help.

Loxy618
Posts: 11
Joined: Wed Apr 24, 2019 2:01 am

Re: Adding more Exceptions

Post by Loxy618 » Thu Apr 25, 2019 12:50 pm

dhylands wrote:
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).
It doesn't look like these links are valid anymore. Does anyone have any examples of how to do this, especially the setting the exception in C and then handling it in python.

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

Re: Adding more Exceptions

Post by dhylands » Thu Apr 25, 2019 1:57 pm

Using nlr_raise is the only way to raise an exception from C. Here's an example:
https://github.com/micropython/micropyt ... mer.c#L626

Here's an example of raising an SystemExit:
https://github.com/micropython/micropyt ... ine.c#L246

Catching an exception in python is just the standard python syntax:
https://docs.python.org/3/tutorial/erro ... exceptions

Post Reply