2 votes

Python 3 handling error TypeError: catching classes that do not inherit from BaseException is not allowed

When I run this code:

i=0
while i<5:
    i=i+1;
    try:
        SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
    except client.get_order as e:
        print ("This is an error message!{}".format(i))
#End while

Obtengo el siguiente error: TypeError: catching classes that do not inherit from BaseException is not allowed

I read this question in stack Exception TypeError warning sometimes shown, sometimes not when using throw method of generator and I also read this: https://medium.com/python-pandemonium/a-very-picky-except-in-python-d9b994bdf7f0

With this code I can partially solve it, since the iterations continue but I cannot capture the error code and print it.

i=0
while i<5:
    i=i+1;
    try:
        SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
    except:
        print ("This is an error message!{}".format(i))
#End while

Thank you very much

1voto

abulafia Points 18959

The error occurs because in the clause except you must indicate which exception you capture. An exception is a class that inherits (directly or indirectly) from the base class. Exception .

On the other hand, you have put client.get_order where python expected the name of the exception, and that you have put is a method of an object, and not a class that inherits from Exception .

You have two solutions, the bad and the good.

The bad is to capture directly Exception as follows:

try:
    SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
except Exception as e:
    print ("This is an error message!{}".format(e))

The block try could generate different exceptions, for different reasons. Since whatever exception is generated, it will inherit from Exception your except will capture it. But this means that you will treat all exceptions that may occur in the same way, which is usually not the best thing to do. The right thing to do would be to have multiple blocks except one for each possible exception, and handle each one accordingly.

So, the good is to capture each possible exception individually:

try:
    SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
except Exception1 as e:
    # Codigo para manejar Exception1
except Exception2 as e:
    # Codigo para manejar Exception2
# etc.

If the exception that occurs is not one of those that you had foreseen, it will be "raised" to the function that called yours, and if the latter does not handle it properly either, it will continue to be raised until it perhaps "breaks" the execution of the program and is shown to the user.

It is tempting to add a final block except Exception as e: to capture everything that has not entered through one of the previous blocks, but in that case you would be masking a possible error in your program. The error would occur anyway, and if not handled correctly could influence the results of other parts. It is better to let the program break in case of unforeseen errors, and then add them in its corresponding except to manage them.

In fact, in your case you probably don't know what exceptions your block may raise. try: . You would have to look at the documentation to find out and write down your except specific, or do not put the try: If the program breaks, let the program break, and examine the error it displays to find out "the hard way" what exception it produced.

Again, it is tempting to put a except Exception as e: to capture all of them, whatever they are, so that you don't have to keep checking what each possible exception is, but it is not the best solution. You can temporarily use that mechanism, so that instead of breaking the program, it shows you which exception it was ( print(e) ) and then add the except specific, but it can be dangerous for the program to continue executing after a not correctly handled exception has occurred, so it is better not to handle it at all, as this will also show which exception occurred and also will stop the program .

Update

Following the additional information provided by the user in some comments, I can be a little more specific in the code example.

It appears that the library is being used python-binance which states a couple of exceptions . If we want to catch those specifically, they need to be declared because they are not standard exceptions that python recognizes in advance. It is enough to import their definition from the appropriate module:

from binance.exceptions import BinanceAPIException, BinanceWithdrawException

BinanceAPIException is a somewhat unique exception. It indicates that when invoking an API (remote, I understand) an error has occurred. Instead of generating a different exception for each possible error, this library has chosen to generate a single exception and provide the user, within the field code of the exception, the numeric error code returned by the API. This forces the user to look at the API documentation to figure out the meaning of all possible error codes .

Therefore, the exception handling code in this particular case could look like this:

try:
    SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
except BinanceAPIException as e:
    print("Excepción en la API.", generar_mensaje(e.code)) 
except BinanceWithdrawException as e:
    print("Ha fallado la retirada de fondos")
except Exception as e:
    # Esto último no debería hacerse, capturar una excepción "comodin"
    # y no tratarla puede llevar a errores
    print("Se ha producido otra excepción no prevista")
    print("Razón:", e)

And then you can create the function generar_mensaje(c) to return an appropriate string for the numeric code c . For example:

def generar_mensaje(c):
   codigos = {
     -1002: "No autorizado",
     -1003: "Demasiadas peticiones",
     -1007: "Timeout",
     -1015: "Demasiadas nuevas órdenes",
     -1100: "Caracteres ilegales",
     -2013: "La orden no existe",
   }
   msg = codigos.get(c, "[Mensaje no traducido]")
   return "Código: {}. {}".format(c, msg)

Notes the use of .get() to get the message with the given code, providing a default value if the code is not found in the dictionary.

0 votes

The try: I am using it because it generates connection errors and I want it to retry when it generates the error, but the intention of printing the error is "just in case" there is another error that is not a connection error.

0 votes

This is the documentation of the bookstore as for exceptions, with your advice applying the "bad" solution I have managed to print the error messages now the challenge is to know what are the exceptions, with except BinanceAPIException as e: I get NameError: name 'BinanceAPIException' is not defined. Thanks, I have to keep reading

0 votes

Reading the official API error codes I managed to do this: try: SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,re‌​cvWindow=Delay) except Exception as e: if e.code==-2013: print ("Order does not exist"); #End If So placing an else if within the exception for each error code seems to me to be the most appropriate.

0voto

Bryro Points 4241

you can do it like this:

i=0
while i<5:
    i=i+1;
    try:
        SellSta=client.get_order(symbol=Symb,orderId=SellOrderNum,recvWindow=Delay)
    except as e:
        print (f"This is an error message!{e}")
#End while

HolaDevs.com

HolaDevs is an online community of programmers and software lovers.
You can check other people responses or create a new question if you don't find a solution

Powered by:

X