Show More
@@ -232,6 +232,8 b' class TaskRejectError(KernelError):' | |||||
232 |
|
232 | |||
233 | class CompositeError(RemoteError): |
|
233 | class CompositeError(RemoteError): | |
234 | """Error for representing possibly multiple errors on engines""" |
|
234 | """Error for representing possibly multiple errors on engines""" | |
|
235 | tb_limit = 4 # limit on how many tracebacks to draw | |||
|
236 | ||||
235 | def __init__(self, message, elist): |
|
237 | def __init__(self, message, elist): | |
236 | Exception.__init__(self, *(message, elist)) |
|
238 | Exception.__init__(self, *(message, elist)) | |
237 | # Don't use pack_exception because it will conflict with the .message |
|
239 | # Don't use pack_exception because it will conflict with the .message | |
@@ -256,22 +258,28 b' class CompositeError(RemoteError):' | |||||
256 |
|
258 | |||
257 | def __str__(self): |
|
259 | def __str__(self): | |
258 | s = str(self.msg) |
|
260 | s = str(self.msg) | |
259 | for en, ev, etb, ei in self.elist: |
|
261 | for en, ev, etb, ei in self.elist[:self.tb_limit]: | |
260 | engine_str = self._get_engine_str(ei) |
|
262 | engine_str = self._get_engine_str(ei) | |
261 | s = s + '\n' + engine_str + en + ': ' + str(ev) |
|
263 | s = s + '\n' + engine_str + en + ': ' + str(ev) | |
|
264 | if len(self.elist) > self.tb_limit: | |||
|
265 | s = s + '\n.... %i more exceptions ...' % (len(self.elist) - self.tb_limit) | |||
262 | return s |
|
266 | return s | |
263 |
|
267 | |||
264 | def __repr__(self): |
|
268 | def __repr__(self): | |
265 | return "CompositeError(%i)"%len(self.elist) |
|
269 | return "CompositeError(%i)" % len(self.elist) | |
266 |
|
270 | |||
267 | def render_traceback(self, excid=None): |
|
271 | def render_traceback(self, excid=None): | |
268 | """render one or all of my tracebacks to a list of lines""" |
|
272 | """render one or all of my tracebacks to a list of lines""" | |
269 | lines = [] |
|
273 | lines = [] | |
270 | if excid is None: |
|
274 | if excid is None: | |
271 | for (en,ev,etb,ei) in self.elist: |
|
275 | for (en,ev,etb,ei) in self.elist[:self.tb_limit]: | |
272 | lines.append(self._get_engine_str(ei)) |
|
276 | lines.append(self._get_engine_str(ei)) | |
273 | lines.extend((etb or 'No traceback available').splitlines()) |
|
277 | lines.extend((etb or 'No traceback available').splitlines()) | |
274 | lines.append('') |
|
278 | lines.append('') | |
|
279 | if len(self.elist) > self.tb_limit: | |||
|
280 | lines.append( | |||
|
281 | '... %i more exceptions ...' % (len(self.elist) - self.tb_limit) | |||
|
282 | ) | |||
275 | else: |
|
283 | else: | |
276 | try: |
|
284 | try: | |
277 | en,ev,etb,ei = self.elist[excid] |
|
285 | en,ev,etb,ei = self.elist[excid] |
@@ -622,6 +622,33 b' class TestView(ClusterTestCase, ParametricTestCase):' | |||||
622 | self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout) |
|
622 | self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout) | |
623 | self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout) |
|
623 | self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout) | |
624 |
|
624 | |||
|
625 | def test_compositeerror_truncate(self): | |||
|
626 | """Truncate CompositeErrors with many exceptions""" | |||
|
627 | view = self.client[:] | |||
|
628 | msg_ids = [] | |||
|
629 | for i in range(10): | |||
|
630 | ar = view.execute("1/0") | |||
|
631 | msg_ids.extend(ar.msg_ids) | |||
|
632 | ||||
|
633 | ar = self.client.get_result(msg_ids) | |||
|
634 | try: | |||
|
635 | ar.get() | |||
|
636 | except error.CompositeError as e: | |||
|
637 | pass | |||
|
638 | else: | |||
|
639 | self.fail("Should have raised CompositeError") | |||
|
640 | ||||
|
641 | lines = e.render_traceback() | |||
|
642 | with capture_output() as io: | |||
|
643 | e.print_traceback() | |||
|
644 | ||||
|
645 | self.assertTrue("more exceptions" in lines[-1]) | |||
|
646 | count = e.tb_limit | |||
|
647 | ||||
|
648 | self.assertEqual(io.stdout.count('ZeroDivisionError'), 2 * count, io.stdout) | |||
|
649 | self.assertEqual(io.stdout.count('by zero'), count, io.stdout) | |||
|
650 | self.assertEqual(io.stdout.count(':execute'), count, io.stdout) | |||
|
651 | ||||
625 | @dec.skipif_not_matplotlib |
|
652 | @dec.skipif_not_matplotlib | |
626 | def test_magic_pylab(self): |
|
653 | def test_magic_pylab(self): | |
627 | """%pylab works on engines""" |
|
654 | """%pylab works on engines""" |
@@ -560,25 +560,25 b' more other types of exceptions. Here is how it works:' | |||||
560 | In [79]: dview.execute("1/0") |
|
560 | In [79]: dview.execute("1/0") | |
561 | [0:execute]: |
|
561 | [0:execute]: | |
562 | --------------------------------------------------------------------------- |
|
562 | --------------------------------------------------------------------------- | |
563 |
ZeroDivisionError Traceback (most recent call last) |
|
563 | ZeroDivisionError Traceback (most recent call last) | |
564 | ----> 1 1/0 |
|
564 | ----> 1 1/0 | |
565 | ZeroDivisionError: integer division or modulo by zero |
|
565 | ZeroDivisionError: integer division or modulo by zero | |
566 |
|
566 | |||
567 | [1:execute]: |
|
567 | [1:execute]: | |
568 | --------------------------------------------------------------------------- |
|
568 | --------------------------------------------------------------------------- | |
569 |
ZeroDivisionError Traceback (most recent call last) |
|
569 | ZeroDivisionError Traceback (most recent call last) | |
570 | ----> 1 1/0 |
|
570 | ----> 1 1/0 | |
571 | ZeroDivisionError: integer division or modulo by zero |
|
571 | ZeroDivisionError: integer division or modulo by zero | |
572 |
|
572 | |||
573 | [2:execute]: |
|
573 | [2:execute]: | |
574 | --------------------------------------------------------------------------- |
|
574 | --------------------------------------------------------------------------- | |
575 |
ZeroDivisionError Traceback (most recent call last) |
|
575 | ZeroDivisionError Traceback (most recent call last) | |
576 | ----> 1 1/0 |
|
576 | ----> 1 1/0 | |
577 | ZeroDivisionError: integer division or modulo by zero |
|
577 | ZeroDivisionError: integer division or modulo by zero | |
578 |
|
578 | |||
579 | [3:execute]: |
|
579 | [3:execute]: | |
580 | --------------------------------------------------------------------------- |
|
580 | --------------------------------------------------------------------------- | |
581 |
ZeroDivisionError Traceback (most recent call last) |
|
581 | ZeroDivisionError Traceback (most recent call last) | |
582 | ----> 1 1/0 |
|
582 | ----> 1 1/0 | |
583 | ZeroDivisionError: integer division or modulo by zero |
|
583 | ZeroDivisionError: integer division or modulo by zero | |
584 |
|
584 | |||
@@ -595,7 +595,7 b' If you want, you can even raise one of these original exceptions:' | |||||
595 | ....: |
|
595 | ....: | |
596 | ....: |
|
596 | ....: | |
597 | --------------------------------------------------------------------------- |
|
597 | --------------------------------------------------------------------------- | |
598 |
ZeroDivisionError Traceback (most recent call last) |
|
598 | ZeroDivisionError Traceback (most recent call last) | |
599 | ----> 1 1/0 |
|
599 | ----> 1 1/0 | |
600 | ZeroDivisionError: integer division or modulo by zero |
|
600 | ZeroDivisionError: integer division or modulo by zero | |
601 |
|
601 | |||
@@ -608,25 +608,25 b' instance:' | |||||
608 | In [81]: dview.execute('1/0') |
|
608 | In [81]: dview.execute('1/0') | |
609 | [0:execute]: |
|
609 | [0:execute]: | |
610 | --------------------------------------------------------------------------- |
|
610 | --------------------------------------------------------------------------- | |
611 |
ZeroDivisionError Traceback (most recent call last) |
|
611 | ZeroDivisionError Traceback (most recent call last) | |
612 | ----> 1 1/0 |
|
612 | ----> 1 1/0 | |
613 | ZeroDivisionError: integer division or modulo by zero |
|
613 | ZeroDivisionError: integer division or modulo by zero | |
614 |
|
614 | |||
615 | [1:execute]: |
|
615 | [1:execute]: | |
616 | --------------------------------------------------------------------------- |
|
616 | --------------------------------------------------------------------------- | |
617 |
ZeroDivisionError Traceback (most recent call last) |
|
617 | ZeroDivisionError Traceback (most recent call last) | |
618 | ----> 1 1/0 |
|
618 | ----> 1 1/0 | |
619 | ZeroDivisionError: integer division or modulo by zero |
|
619 | ZeroDivisionError: integer division or modulo by zero | |
620 |
|
620 | |||
621 | [2:execute]: |
|
621 | [2:execute]: | |
622 | --------------------------------------------------------------------------- |
|
622 | --------------------------------------------------------------------------- | |
623 |
ZeroDivisionError Traceback (most recent call last) |
|
623 | ZeroDivisionError Traceback (most recent call last) | |
624 | ----> 1 1/0 |
|
624 | ----> 1 1/0 | |
625 | ZeroDivisionError: integer division or modulo by zero |
|
625 | ZeroDivisionError: integer division or modulo by zero | |
626 |
|
626 | |||
627 | [3:execute]: |
|
627 | [3:execute]: | |
628 | --------------------------------------------------------------------------- |
|
628 | --------------------------------------------------------------------------- | |
629 |
ZeroDivisionError Traceback (most recent call last) |
|
629 | ZeroDivisionError Traceback (most recent call last) | |
630 | ----> 1 1/0 |
|
630 | ----> 1 1/0 | |
631 | ZeroDivisionError: integer division or modulo by zero |
|
631 | ZeroDivisionError: integer division or modulo by zero | |
632 |
|
632 | |||
@@ -654,11 +654,31 b' instance:' | |||||
654 | ipdb> e.print_traceback(1) |
|
654 | ipdb> e.print_traceback(1) | |
655 | [1:execute]: |
|
655 | [1:execute]: | |
656 | --------------------------------------------------------------------------- |
|
656 | --------------------------------------------------------------------------- | |
657 |
ZeroDivisionError Traceback (most recent call last) |
|
657 | ZeroDivisionError Traceback (most recent call last) | |
658 | ----> 1 1/0 |
|
658 | ----> 1 1/0 | |
659 | ZeroDivisionError: integer division or modulo by zero |
|
659 | ZeroDivisionError: integer division or modulo by zero | |
660 |
|
660 | |||
661 |
|
661 | |||
|
662 | Since you might have 100 engines, you probably don't want to see 100 tracebacks | |||
|
663 | for a simple NameError because of a typo. | |||
|
664 | For this reason, CompositeError truncates the list of exceptions it will print | |||
|
665 | to :attr:`CompositeError.tb_limit` (default is five). | |||
|
666 | You can change this limit to suit your needs with: | |||
|
667 | ||||
|
668 | .. sourcecode:: ipython | |||
|
669 | ||||
|
670 | In [20]: from IPython.parallel import CompositeError | |||
|
671 | In [21]: CompositeError.tb_limit = 1 | |||
|
672 | In [22]: %px a=b | |||
|
673 | [0:execute]: | |||
|
674 | --------------------------------------------------------------------------- | |||
|
675 | NameError Traceback (most recent call last) | |||
|
676 | ----> 1 a=b | |||
|
677 | NameError: name 'b' is not defined | |||
|
678 | ||||
|
679 | ... 3 more exceptions ... | |||
|
680 | ||||
|
681 | ||||
662 | All of this same error handling magic even works in non-blocking mode: |
|
682 | All of this same error handling magic even works in non-blocking mode: | |
663 |
|
683 | |||
664 | .. sourcecode:: ipython |
|
684 | .. sourcecode:: ipython | |
@@ -670,25 +690,8 b' All of this same error handling magic even works in non-blocking mode:' | |||||
670 | In [85]: ar.get() |
|
690 | In [85]: ar.get() | |
671 | [0:execute]: |
|
691 | [0:execute]: | |
672 | --------------------------------------------------------------------------- |
|
692 | --------------------------------------------------------------------------- | |
673 |
ZeroDivisionError Traceback (most recent call last) |
|
693 | ZeroDivisionError Traceback (most recent call last) | |
674 | ----> 1 1/0 |
|
|||
675 | ZeroDivisionError: integer division or modulo by zero |
|
|||
676 |
|
||||
677 | [1:execute]: |
|
|||
678 | --------------------------------------------------------------------------- |
|
|||
679 | ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>() |
|
|||
680 | ----> 1 1/0 |
|
694 | ----> 1 1/0 | |
681 | ZeroDivisionError: integer division or modulo by zero |
|
695 | ZeroDivisionError: integer division or modulo by zero | |
682 |
|
696 | |||
683 | [2:execute]: |
|
697 | ... 3 more exceptions ... | |
684 | --------------------------------------------------------------------------- |
|
|||
685 | ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>() |
|
|||
686 | ----> 1 1/0 |
|
|||
687 | ZeroDivisionError: integer division or modulo by zero |
|
|||
688 |
|
||||
689 | [3:execute]: |
|
|||
690 | --------------------------------------------------------------------------- |
|
|||
691 | ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>() |
|
|||
692 | ----> 1 1/0 |
|
|||
693 | ZeroDivisionError: integer division or modulo by zero |
|
|||
694 |
|
General Comments 0
You need to be logged in to leave comments.
Login now