1

I am using gspread module to read stuff from a Google Sheet using Python. Sometimes, I hit an error which I can trace from the Python console.

But I would like my Python code to handle it, and tell me as much details as possible about what is causing the error. I suppose this should be done using try/catch, but I couldn't find any examples to understand...

  • how to get info from gspread about the gspread error details, and
  • how to handle it into a dictionary so I can print out the error myself.
    import gspread
    try:
        # do some stuff
    except gspread.exceptions.APIError as e:
        print("ERROR", e, type(e))
        # what should I put in the previous lines to handle the exception
        # and get the error details into a python variable, i.e. err
        # print("Error {}: {}".format(err['code'], err['name']))
        # print(" (raised by {} line {})".format(err['script'], err['line']))

current output (for example if I try to access a file which is not mine):

ERROR {
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "File not found: 1eIjkFBQmTo2TCr7hf4HFItSsBQmGAT-t3ZXH1LlEmNk",
    "locationType": "other",
    "location": "file"
   }
  ],
  "code": 404,
  "message": "File not found: 1eIjkFBQmTo2TCr7hf4HFItSsBQmGAT-t3ZXH1LlEmNk"
 }
}
 <class 'gspread.exceptions.APIError'>

My main concern is getting error code and error name/description into a variable (dictionary, list or whatever ... I don't care).

But if I could also get the script & line of my code which raised the error, that would be great.

abu
  • 422
  • 7
  • 14
  • Does this answer your question? [When I catch an exception, how do I get the type, file, and line number?](https://stackoverflow.com/questions/1278705/when-i-catch-an-exception-how-do-i-get-the-type-file-and-line-number) – Tomerikoo Feb 07 '21 at 18:01
  • thanks @Tomerikoo , but I think my problem is more focused in the particular way of parsing gspread returned errors (see my edit) – abu Feb 07 '21 at 18:28
  • Well, you already have above most the information you need so just add the file and line number from the link. Am I missing something? – Tomerikoo Feb 07 '21 at 18:30
  • lol ... you are missing that I don't know how to parse that e variable into its different parts: ¿should I use e.error.errors[0].message? But that does not work. No idea about how to extract the info (so, your link is useful, but not for the main part of my problem ... just for the extra info I wanted) – abu Feb 07 '21 at 18:32
  • Oh I see. Try `e.args`. See the last example of [Handling Exceptions](https://docs.python.org/3/tutorial/errors.html#handling-exceptions) – Tomerikoo Feb 07 '21 at 18:35
  • e.args didn't seem to be useful in this case ... looks like to me that all gspread error information is being returned as a json string – abu Feb 07 '21 at 19:38

1 Answers1

0

It seems that all gspread error information was being returned as a json string, so my problem was knowing how to parse it to access its elements:

import gspread
try:
    # do some stuff
except gspread.exceptions.APIError as e:
    import json,os
    ej = json.loads(str(e))["error"]
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    err = {'code':ej['code'], 'message':ej['message'],'script':fname, 'line':exc_tb.tb_lineno}
    print("Error {}: {}".format(err['code'], err['message']))
    print(" (raised by {} line {})".format(err['script'], err['line']))

Thanks @Tomerikoo for the link about file and line information.

That was it !

Hopefully @Burnash (gspread developer) can tell us if there is a more direct way to get error codes & messages.

abu
  • 422
  • 7
  • 14
  • Happy to help! Out of curiosity, what did `e.args` produce? I doubt that you should convert the error to a string just to parse as a json dict. Surely you can get that data directly. Maybe `e.args[0]`? – Tomerikoo Feb 07 '21 at 19:42
  • It also was strange to me, so that motivated my question. I wonder if there is a way to store and post the Python e object so you can deal with it. type(e): ; type(e.args): ; type(e.args[0]): ; type(e.args[1]): IndexError: tuple index out of range – abu Feb 08 '21 at 10:15
  • I see. So at least that answers one part of my question. By doing `e.args[0]` you get that data - just in a string format... Still, at least your solution code is not very complicated – Tomerikoo Feb 08 '21 at 10:24
  • Yes, but I still don't know hot to get the error code, other than doing this odd thing: json.loads(e.args[0])["error"]["code"] – abu Feb 08 '21 at 10:27
  • I don't think it's very odd... It's perfectly normal data "getter". The only thing ***I*** find odd is that you even need to do `json.loads(f.args[0])`. I would expect it to be possible to do `e.args[0]["error"]["code"]`. But, again, as I said your code is very simple and clear so you got off easy :) – Tomerikoo Feb 08 '21 at 10:29