On Thu, Apr 09, 2020 at 08:27:14AM -0300, Soni L. wrote:
To put it simple, unpacking raises ValueError:
But if the iterator raises ValueError, there's no way to tell it apart from the unpacking:
... yield None ... raise ValueError
You could start by reading the error message and the traceback, that will usually make it clear the nature of the value error, and where it occurred (in the generator, or where the generator was consumed).
For *debugging purposes* this is usually sufficient: the person reading the exception can tell the difference between an unpacking error:
# outside the iterator a, b, c = iterator ValueError: not enough values to unpack (expected 3, got 1)
and some other error:
# inside the iterator yield int('aaa') ValueError: invalid literal for int() with base 10: 'aaa'
There may be rare cases where it is difficult to tell. Perhaps the traceback is missing, or you are debugging a byte-code only library, or obfuscated code, say. But these are rare cases, and we don't have to solve those problems in the language.
Where this is not sufficient is for error recovery:
try: a, b, c = iterator except ValueError: recover()
However, this is also true for every exception that Python might raise. There is no absolutely foolproof solution, but it is usually good enough to e.g.:
- include as little as possible inside the `try` block;
- carefully audit the contents of the `try` block to ensure it cannot raise the exception you want to catch;
- wrap the iterator in something that will convert ValueError to another exception.
At one point some years ago I attempted to write an "Exception Guard" object that caught an exception and re-raised it as another exception, so you could do this:
guard = ExceptionGuard(catch=ValueError, throw=RuntimeError) try: a, b, c = guard(iterator) except ValueError: print('unpacking error') except RuntimeError: print('ValueError in iterator caught and coverted')
but it collapsed under the weight of over-engineering and trying to support versions of Python back to 2.4, and I abandoned it. Perhaps you will have better luck, and when you have it as a mature, working object, you can propose it for the standard library.