具有不同特定消息的相同例外

时间:2015-02-14 19:10:36

标签: python error-handling python-3.4

我尝试编写一个可以区分以下四种不同错误的代码。

  1. TypeError:第一个参数不是整数;
  2. TypeError:第二个参数不是字符串;
  3. ValueError:第一个参数的值不在113的范围内;或
  4. ValueError:第二个参数的值不是集{'s', 'h', 'c', 'd'}中的其中一个字符串。
  5. 但是,我只能让第一个工作,而不是其他三个错误。我尝试了不同的方法让它发挥作用,但仍然无法弄清楚是什么错误。

    class Card: # One object of class Card represents a playing card
    
        rank = ['','Ace','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King']
        suit = {'d':'Diamonds', 'c':'Clubs', 'h':'Hearts', 's':'Spades'}
    
        def __init__(self, rank=2, suit=0): # Card constructor, executed every time a new Card object is created
            if type(rank) != int:
                raise TypeError()
            if type(suit) != str:
                raise TypeError()
            if rank != self.rank:
                raise ValueError()
            if suit != 'd' or 'c' or 'h' or 's':
                raise ValueError()
            self.rank = rank
            self.suit = suit
    
        def getRank(self): # Obtain the rank of the card
            return self.rank
    
        def getSuit(self): # Obtain the suit of the card
            return Card.suit[self.suit]
    
        def bjValue(self): # Obtain the Blackjack value of a card
            return min(self.rank, 10)
    
        def __str__(self): # Generate the name of a card in a string
            return "%s of %s" % (Card.rank[int(self.rank)], Card.suit[self.suit])
    
    if __name__ == "__main__": # Test the class Card above and will be skipped if it is imported into separate file to test
        try:
            c1 = Card(19,13)
        except TypeError:
            print ("The first parameter is not an integer")
        except TypeError:
               print ("The second parameter is not a string")
        except ValueError:
            print ("The value of first parameter is not in the range of 1 to 13")
        except ValueError:
            print ("The value of second parameter is not one of the strings in the set {'s','h','c','d'}")
    
        print(c1)
    

    我知道也许是因为我有TypeErrorValueError。因此,Python无法区分我点击TypeError的第二个c1 = Card(13,13)与第一个TypeError不同的"The first parameter is not an integer"。所以,当我有c1 = Card(13,13)时,我只收到{{1}}的消息。

1 个答案:

答案 0 :(得分:1)

您正试图区分完全错误的地方中的错误来源。当错误超出Card.__init__时,无法告诉为什么,例如抛出了TypeError。对于每个错误类(TypeErrorValueError,只会触发第一个 except

try:
    ...
except TypeError:
    # all TypeErrors end up here
except TypeError:
    # this is *never* reached
except ValueError:
    # all ValueErrors end up here
except ValueError:
    # this is *never* reached

相反,当您实际Card.__init__错误且已经知道原因是什么时,您应该在 raise内提供具体的错误消息

if not isinstance(rank, int):  # better than comparing to type
    raise TypeError("The first parameter is not an integer")

然后你可以更简单地处理它们:

try:
    c1 = Card(19,13)
except (TypeError, ValueError) as err:  # assign the error to the name 'err'
    print(err)  # whichever we catch, show the user the message
else:
    print(c1)  # only print the Card if there were no errors

如果您特别需要区分同一类的不同错误,您可以明确检查消息:

except TypeError as err:
    if err.args[0] == "The first parameter is not an integer":
        # do whatever you need to

或创建您自己的,更具体的Exception子类,这样您就可以拥有单独的except块:

class FirstParamNotIntError(Exception):
    pass

(这只是一个例子,它们在您的特定情况下过于具体)。


阅读the documentation on exceptionsthe tutorial on using them可能值得一读。