Python Forum
Thread Rating:
  • 1 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
raising multiple exceptions
#1
in a function that is to be given a list of tuples i want to raise an exception for an error.  for example each tuple must be of length 2 or 3 and the first element must always be a string.  anything else makes no sense, or is ambiguous.  i want to raise an exception for this kind of error.  for an empty list it will just return None (an empty list means nothing to do).  it would be nice to see what all the errors are in the first bad run so they all can be fixed in one cycle.  i was thinking of outputting an error message describing each error then raise an exception if there were any errors.  but i have heard of schemes used to record exceptions with their types and descriptions.  that sounds like i need to raise an exception for each errorhow should i approach this?  back in my C days i would do the multiple output approach since the only exception handling there was, was to exit/kill the process.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
Something like this? Subclassing the tuple class
In [19]: class Mytup(tuple):
    ...:     def __new__(cls, obj):
    ...:         if 2 <= len(obj) <= 3 and isinstance(obj[0], str):
    ...:             return tuple.__new__(cls, obj)
    ...:         elif 2 > len(obj) > 3:
    ...:             raise Exception("Wrong number of arguments in {}".format(obj.__repr__()))
    ...:         elif isinstance(obj[0], str):
    ...:             raise Exception("{} must be string! {} is given.".format(obj[0], type(obj[0])))
    ...:                

In [20]: x = Mytup(['yes', 2, 3])

In [21]: x
Out[21]: ('yes', 2, 3)

In [22]: x = Mytup([42, 2, 3])

In [23]: x

In [24]: print(x)
None
Except it didn't rise an Exception.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#3
I think he wants the exceptions to be triggered

class Mytup(tuple):
    def __new__(cls, obj):
        if not obj:
            return None
        elif 2 > len(obj) > 3:
            raise Exception("Wrong number of arguments in {}".format(obj.__repr__()))
        elif not isinstance(obj[0], str):
            raise Exception("{} must be string! {} is given.".format(obj[0], type(obj[0])))
        else:
            return tuple.__new__(cls, obj)
            
x = Mytup(['yes', 2, 3])
print(x)
x = Mytup([])
print(x)
x = Mytup([42, 2, 3])
print(x)
Output:
('yes', 2, 3) None Traceback (most recent call last):   File "test2.py", line 17, in <module>     x = Mytup([42, 2, 3])   File "test2.py", line 9, in __new__     raise Exception("{} must be string! {} is given.".format(obj[0], type(obj[0]))) Exception: 42 must be string! <type 'int'> is given.
Recommended Tutorials:
Reply
#4
(Mar-18-2017, 12:45 PM)metulburr Wrote: I think he wants the exceptions to be triggered
Yes, I noticed it but mine didn't work. Don't know why. I am not dating with classes very often
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#5
Condition 2 > len(obj) > 3 should be  rewritten as False , less typing :)  a > x > b means a > x and x > b, not a > x or x > b.

I think that Skaparen wants to do something like (pseudocode) :
line 1  # triggers exception1
line 2  # triggers exception2
line 3  # triggers exception3

raise exception1 and exception2 and exception3
I dont think that something such that could be done easily (well, you can use lot of try/except, store exception infos to a list, extend Exception to accept another parameter and at the end of code do raise MySuperException('exceptions', list_of_exceptions) to send info about all exceptions if your list_of_exceptions is not empty ... but why?).

If you insist on "ignoring" exceptions and going on, why not just log it?
import logging
logging.basicConfig(filename='logfile.log')

try:
    1/0
except:
    logging.exception("my exception comment")

try:
    int("foo")
except:
    logging.exception("another comment")
Output:
ERROR:root:my exception comment Traceback (most recent call last):   File "exceptlog.py", line 9, in <module>     1/0 ZeroDivisionError: division by zero ERROR:root:another comment Traceback (most recent call last):   File "exceptlog.py", line 14, in <module>     int("foo") ValueError: invalid literal for int() with base 10: 'foo'
Reply
#6
Except I think he wants all the exceptions raised at once. That is, if it's four long and starts with an int, it should raise two exceptions. But you can't really do that, AFAIK. The closest you could get is raising an exception while handling another exception, but that would imply a try/except block somewhere to handle the first exception. I think that would just be a mess:

try:
    if not 2 <= len(x) <= 3:
        raise ValueError('Size must be two or three.')
except ValueError:
    if not isinstance(x[0], str):
        raise ValueError('First item must be string.')
if not isinstance(x[0], str):
    raise ValueError('First item must be string.')
You have to check the first item twice, once if there is a length error and once if there isn't. If you have three items to check it becomes huge.

So if you want all the errors at once, you would want to collect the error conditions without raising exceptions, and then raise one exception if you found any error conditions. However, if you're doing this for development purposes, I would do it with unit tests. Have one test for each condition, and the run all the tests to see which ones throw exceptions.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#7
I think he wants to get all exception at once as he says: "it would be nice to see what all the errors are in the first bad run so they all can be fixed in one cycle. "
So, logging will come in handy but I never touch it, though. However, it points to some direction at least.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#8
for each item in the list, i want to check it for errors in some order and raise one exception for that one item.  but the list may contain 6144 items of which #89, #1024, #4317, and #6133 have an error.  i want to let whoever deals with fixing these know about all of the errors.  if the tuple is too long and has an int as the first item in the tuple, then it is good enough to indicate it is too long.  being too long, the contents no longer makes any sense, so the type of the first element of the tuple is not relevant.  what i need to do is point out all 4 errors (or however many there really are).

what would be nice is a means to do the raise in a way that keeps on running.  but then that makes no sense to outer layer code that is catching the exception(s). multiple threads could create new problems and many bugs.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#9
Well, instead of raising errors it can check for conditions and if the tuple is out of what is wanted, to put messages indicating the problems found in a dictionary and the index of the tuple as the key, returning None.
Something like this? I don't know if the error dictionary must be passed as an argument to the class definition. Can't test it now.
But you get the idea
from collections import defaultdict

def tuples_validation(tuples):
    errors = defaultdict(list)
    
    class Mytup(tuple):
        def isvalid(self, index, obj):
            valid = True
            
            if obj:
                errors[index].append("An empy tuple")
                valid = False
            if 2 > len(obj) > 3:
                erros[index].append("Wrong number of arguments in {}".format(obj.__repr__()))
                valid = False
            if isinstance(obj[0], str):
                errors[index].append("{} must be string! {} is given.".format(obj[0], type(obj[0])))
                valid = False
            
            return valid
            
            def __new__(cls, obj):
            if self.valid(obj):
                return None
            else:
                return tuple.__new__(cls, obj)
    
    new_tuples = []
    for t in tuples:
        new_t = Mytup(tuples.index(t), t)
        if new_t:
            new_tuples.append(new_t)
        #~ else:
            #~ pass
            
    return (errors, new_tuples)
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#10
using a defaultdict looks interesting.  i still don't understand all of it.  when would it be better than a plain dict using .get() to fetch from it?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  PiCamera - print exceptions? korenron 2 792 Dec-15-2022, 10:48 PM
Last Post: Larz60+
  SystemError: initialization of integer failed without raising an exception Anldra12 2 4,293 Apr-19-2022, 10:50 AM
Last Post: Anldra12
  Class exceptions DPaul 1 1,259 Mar-11-2022, 09:01 AM
Last Post: Gribouillis
  is this a good way to catch exceptions? korenron 14 4,594 Jul-05-2021, 06:20 PM
Last Post: hussaind
  Raising numbers to power ** GJG 3 2,400 Mar-23-2021, 03:43 PM
Last Post: deanhystad
  Python, exceptions KingKhan248 6 2,948 Nov-15-2020, 06:54 AM
Last Post: buran
  Split string between two different delimiters, with exceptions DreamingInsanity 2 1,984 Aug-24-2020, 08:23 AM
Last Post: DreamingInsanity
  handling 2 exceptions at once Skaperen 2 2,263 Jun-27-2020, 08:55 AM
Last Post: Yoriz
  remove spaces with exceptions catosp 4 2,366 May-29-2020, 09:32 AM
Last Post: catosp
  Looking for advice and Guidance on Exceptions used within Functions paul41 1 2,115 Nov-14-2019, 12:33 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020