0
votes

I am using execnet to call a jython module from within a python script.

From the docs:

Note that exceptions from the remotely executing code will be reraised as channel.RemoteError exceptions containing a textual representation of the remote traceback.

Let's say my remote module could result in two different exceptions, and I would like to be able to handle each exception differently. How will I be able to handle this, given that both exceptions will instead throw a RemoteError exception that only contains a string of the traceback?

For example, this particular calling code:

#...
channel.send('bogus')

results in the following RemoteError, which just contains an attribute formatted that contains a string of the traceback:

RemoteError: Traceback (most recent call last):
  File "<string>", line 1072, in executetask
  File "<string>", line 1, in do_exec
  File "<remote exec>", line 33, in <module>
IOError: Open failed for table: bogus, error: No such file or directory (2)

I cannot do a try ... except IOError:. I could do a try ... except RemoteError as ex: and parse the ex.formatted to see if it contains IOError, and then raise that instead, but this seems rather sloppy:

from execnet.gateway_base import RemoteError
try:
    channel.send('bogus')
except RemoteError as ex:
    if 'IOError' in ex.formatted:
        raise IOError(ex.formatted[ex.formatted.find('IOError'): -1])
    if 'ValueError' in ex.formatted:
        raise ValueError(ex.formatted[ex.formatted.find('ValueError'): -1])
    # otherwise, reraise the uncaptured error:
    raise ex
1

1 Answers

0
votes

An old question - I tried to answer it

import unittest
from execnet.gateway_base import RemoteError
import execnet

class Test(unittest.TestCase):

    def RemoteErrorHandler(self,error):
        e,t = error.formatted.splitlines()[-1].split(':')
        raise getattr(__builtins__,e)(t)

    def raising_receive(self, ch):
        try:
            return ch.receive()
        except RemoteError as ex:
            self.RemoteErrorHandler(ex)

    def setUp(self):
        self.gateway = execnet.makegateway()


    def test_NameError(self):
        ch = self.gateway.remote_exec("print o")
        with self.assertRaises(NameError):
            self.raising_receive(ch)


if __name__ == '__main__':
    unittest.main()