diff --git a/julia/core.py b/julia/core.py index 705359ff..85d5a787 100644 --- a/julia/core.py +++ b/julia/core.py @@ -257,6 +257,7 @@ def __init__(self, init_julia=True, jl_init_path=None): self.api.jl_typename_str.restype = char_p self.api.jl_typeof_str.restype = char_p self.api.jl_unbox_voidpointer.restype = py_object + self.api.jl_bytestring_ptr.restype = char_p if init_julia: try: @@ -295,13 +296,26 @@ def call(self, src): # return null ptr if error ans = self.api.jl_eval_string(src.encode('utf-8')) if not ans: - jexp = self.api.jl_exception_occurred() - exception_str = self._unwrap_exception(jexp).decode('utf-8') - raise JuliaError(u'Exception calling julia src: {}\n{}' - .format(exception_str, src)) + exception_type = self._typeof_julia_exception_in_transit().decode('utf-8') + exception_msg = self._capture_showerror_for_last_julia_exception().decode('utf-8') + raise JuliaError(u'Exception \'{}\' ocurred while calling julia code:\n{}\n\nCode:\n{}' + .format(exception_type, exception_msg, src)) return ans - def _unwrap_exception(self, jl_exc): + def _capture_showerror_for_last_julia_exception(self): + msg = self.api.jl_eval_string(u""" + try + rethrow() + catch e + b = IOBuffer() + showerror(b, e, catch_backtrace()) + seekstart(b) + return readall(b) + end + """) + return self.api.jl_bytestring_ptr(msg) + + def _typeof_julia_exception_in_transit(self): exception = void_p.in_dll(self.api, 'jl_exception_in_transit') msg = self.api.jl_typeof_str(exception) return char_p(msg).value diff --git a/julia/magic.py b/julia/magic.py index 255a3e5d..47c9b47e 100644 --- a/julia/magic.py +++ b/julia/magic.py @@ -21,7 +21,7 @@ import sys from IPython.core.magic import Magics, magics_class, line_cell_magic -from julia import Julia +from julia import Julia, JuliaError #----------------------------------------------------------------------------- # Main classes @@ -55,7 +55,14 @@ def julia(self, line, cell=None): Python namespace. """ src = unicode(line if cell is None else cell) - return self.julia.eval(src) + + try: + ans = self.julia.eval(src) + except JuliaError as e: + print(e.message, file=sys.stderr) + ans = None + + return ans # Add to the global docstring the class information.