@@ -641,7 +641,7 @@ crucial things to keep in mind:
641
641
642
642
* Any unhandled exceptions are re-raised inside the parent task. If
643
643
there are multiple exceptions, then they're collected up into a
644
- single :exc: `MultiError ` exception.
644
+ single :exc: `BaseExceptionGroup ` or :exc: ` ExceptionGroup ` exception.
645
645
646
646
Since all tasks are descendents of the initial task, one consequence
647
647
of this is that :func: `run ` can't finish until all tasks have
@@ -712,14 +712,9 @@ limitation. Consider code like::
712
712
what? In some sense, the answer should be "both of these at once", but
713
713
in Python there can only be one exception at a time.
714
714
715
- Trio's answer is that it raises a :exc: `MultiError ` object. This is a
715
+ Trio's answer is that it raises a :exc: `BaseExceptionGroup ` object. This is a
716
716
special exception which encapsulates multiple exception objects –
717
- either regular exceptions or nested :exc: `MultiError `\s . To make these
718
- easier to work with, Trio installs a custom `sys.excepthook ` that
719
- knows how to print nice tracebacks for unhandled :exc: `MultiError `\s ,
720
- and it also provides some helpful utilities like
721
- :meth: `MultiError.catch `, which allows you to catch "part of" a
722
- :exc: `MultiError `.
717
+ either regular exceptions or nested :exc: `BaseExceptionGroup `\s .
723
718
724
719
725
720
Spawning tasks without becoming a parent
@@ -837,104 +832,6 @@ The nursery API
837
832
See :meth: `~Nursery.start `.
838
833
839
834
840
- Working with :exc: `MultiError `\s
841
- ++++++++++++++++++++++++++++++++
842
-
843
- .. autoexception :: MultiError
844
-
845
- .. attribute :: exceptions
846
-
847
- The list of exception objects that this :exc: `MultiError `
848
- represents.
849
-
850
- .. automethod :: filter
851
-
852
- .. automethod :: catch
853
- :with:
854
-
855
- Examples:
856
-
857
- Suppose we have a handler function that discards :exc: `ValueError `\s ::
858
-
859
- def handle_ValueError(exc):
860
- if isinstance(exc, ValueError):
861
- return None
862
- else:
863
- return exc
864
-
865
- Then these both raise :exc: `KeyError `::
866
-
867
- with MultiError.catch(handle_ValueError):
868
- raise MultiError([KeyError(), ValueError()])
869
-
870
- with MultiError.catch(handle_ValueError):
871
- raise MultiError([
872
- ValueError(),
873
- MultiError([KeyError(), ValueError()]),
874
- ])
875
-
876
- And both of these raise nothing at all::
877
-
878
- with MultiError.catch(handle_ValueError):
879
- raise MultiError([ValueError(), ValueError()])
880
-
881
- with MultiError.catch(handle_ValueError):
882
- raise MultiError([
883
- MultiError([ValueError(), ValueError()]),
884
- ValueError(),
885
- ])
886
-
887
- You can also return a new or modified exception, for example::
888
-
889
- def convert_ValueError_to_MyCustomError(exc):
890
- if isinstance(exc, ValueError):
891
- # Similar to 'raise MyCustomError from exc'
892
- new_exc = MyCustomError(...)
893
- new_exc.__cause__ = exc
894
- return new_exc
895
- else:
896
- return exc
897
-
898
- In the example above, we set ``__cause__ `` as a form of explicit
899
- context chaining. :meth: `MultiError.filter ` and
900
- :meth: `MultiError.catch ` also perform implicit exception chaining – if
901
- you return a new exception object, then the new object's
902
- ``__context__ `` attribute will automatically be set to the original
903
- exception.
904
-
905
- We also monkey patch :class: `traceback.TracebackException ` to be able
906
- to handle formatting :exc: `MultiError `\s . This means that anything that
907
- formats exception messages like :mod: `logging ` will work out of the
908
- box::
909
-
910
- import logging
911
-
912
- logging.basicConfig()
913
-
914
- try:
915
- raise MultiError([ValueError("foo"), KeyError("bar")])
916
- except:
917
- logging.exception("Oh no!")
918
- raise
919
-
920
- Will properly log the inner exceptions:
921
-
922
- .. code-block :: none
923
-
924
- ERROR:root:Oh no!
925
- Traceback (most recent call last):
926
- File "<stdin>", line 2, in <module>
927
- trio.MultiError: ValueError('foo',), KeyError('bar',)
928
-
929
- Details of embedded exception 1:
930
-
931
- ValueError: foo
932
-
933
- Details of embedded exception 2:
934
-
935
- KeyError: 'bar'
936
-
937
-
938
835
.. _task-local-storage :
939
836
940
837
Task-local storage
0 commit comments