5 ms·
try: val = input['foo']['bar'] except KeyError, TypeError: raise HttpErrors.BadRequest
by tgsovlerkhgsel 5y ago
try:
val = input['foo']['bar']
except KeyError, TypeError:
raise HttpErrors.BadRequest
- Kocrachon 5y agoCan someone explain to me why python uses try/except so often? I see that promoted as a solution instead of; if 'bar' in input['foo'].keys(): val = input['foo']['bar'] Generally, exceptions cause code to run slower and I feel like in any other language is considered bad practices. I never understood why Python promotes EAFP vs LBYL. Both performance and accuracy wise, checking before doing is safer and faster performance.
- tgsovlerkhgsel 5y agoYour example will throw a KeyError if "input" doesn't contain "foo", and an AttributeError if "foo" is some unexpected data type that doesn't have keys().
- kortex 5y agoWell, firstly input.get("foo", {}).get("bar", default) is a bit nicer, imho. Python exceptions are only slower on the exception. They are almost exactly the same speed on success. LBYL forces you to look for all the ways in which you might leap. EAFP lets you handle even unexpected conditions. The classic use case is checking if a condition exists, then doing the thing, except the condition changed between check and run. So you gotta catch anyways. I've been moving away from this actually and towards a rust-like Result[T, Exception]. I'm using the package called "result". For fastapi api_request -> handler -> some_func_chain -> return response_to_client patterns, if something barfs, you normally get a 422 and useless "Internal server error". It's far simpler imho to map over some Results and then pack the error(s) into a more useful response. Also testing is just a lot simpler. https://pypi.org/project/result/ https://pypi.org/project/result/
- tptacek 5y agoYou just generated a 502, and spent a bunch of extra lines doing it. The 502 is bad, and if that's all I need to do, I get that almost for free from net/http's panic handler. It sounds like you don't actually have a problem here.
- claudiawerner 5y agoI think that was more of an example. There are lots of ways to fail gracefully when you don't have the data you want in the dict.
- tptacek 5y agoRight, which is why json.Unmarshal returns an error, and why map lookups return an extra `ok` value in Go.
- tgsovlerkhgsel 5y agoIt would be a lot more than 4 lines in Go though. Either the struct definition, or a lot of `if !ok return error`. Especially once the nesting gets deeper.
- tptacek 5y agoI'm pretty sure it would just be an `if err != nil {http.Error(w, err.Error(), 501); return }`.
- tgsovlerkhgsel 5y agoone of these for each nesting level.
- tgsovlerkhgsel 5y agoI kept the example simple, of course I could now customize the error message further (or take some other sensible action). Note that I returned a 400, not a generic 502 here. If I didn't care at all, I wouldn't need any extra lines. Does the panic handler send a response at all, or does it just drop the connection? Also, in Go, using panic/recover is considered unidiomatic. You can use it like an exception system, but it's not what you're supposed to do.
- 5y ago