Page 1 of 1

Micropython Syntax Analysis

Posted: Tue Jan 15, 2019 3:13 pm
by chester20080
Hello to everyone,

Background:

I have a Micropython port running on a custom STM32F4 microcontroller board. The python script to be executed is loaded into the filesystem, and pyexec_file parses, compiles and executes the script. There is no REPL console.

Question:
In case of any python syntax error, I would like somehow to retrieve the error line and the description of the error (E.g Line 13: Unexpected foo var). How can we extract this information from the c code of the micropython? Is there any variable in the c code of the micropython that holds this kind of information?

Re: Micropython Syntax Analysis

Posted: Tue Jan 15, 2019 5:13 pm
by stijn
See definition of pyexec_file which calls parse_compile_execute: the exception is stored in nlr.ret_val and passed to mp_obj_print_exception. If that's not suitable for you there's not much else you can do but implement parse_compile_execute yourself (or adapt it to pass the exception object to your own function or so).

Re: Micropython Syntax Analysis

Posted: Tue Jan 15, 2019 9:12 pm
by dhylands
This python code will record the information into a file. So you may also want to look at the implementation of the sys.print_exception function in C.

Code: Select all

# Exception Test

import sys

def foo():
    raise ValueError('An error happened')

def bar():
    try:
        foo()
    except ValueError as ex:
        with open('exception.txt', 'wb') as f:
            sys.print_exception(ex, f)

print('About to call bar')
bar()
and I get the following in exception.txt:

Code: Select all

Traceback (most recent call last):
  File "exc_test.py", line 10, in bar
  File "exc_test.py", line 6, in foo
ValueError: An error happened

Re: Micropython Syntax Analysis

Posted: Wed Jan 16, 2019 9:04 am
by stijn
The problem is the OP is asking about syntax errors, which happen in the parser already so cannot be caught like that. Unless the entire file execution is wrapped which I think can be done by enabling MICROPY_PY_BUILTINS_EXECFILE to get the execfile function. E.g. principle would be

in C:

Code: Select all

pyexec_file('my_main_wrapper.py')
in my_main_wrapper.py:

Code: Select all

try:
  execfile('my_main.py')
except SyntaxError as e:  # could use this to ditinguish between actual syntax errors and everything else
  write_exception_to_file(e)
except Exception as e:
  write_exception_to_file(e)
or alternatives like:

Code: Select all

try:
  import my_main
  my_main.foo()
except Exception as e:
  write_exception_to_file(e)
and then the actual code goes in my_main.py. This still won't leave a trace of exceptions which might occur my_main_wrapper.py though..