4 ms·
Yeah, the formality of embedded structs can lead to some very verbose bloat. And it obviously only works on very reliable payloads.
by nkozyra 5y ago
Yeah, the formality of embedded structs can lead to some very verbose bloat. And it obviously only works on very reliable payloads.
- tptacek 5y agoWhat's the solution for an unreliable payload? When things aren't where you expect them in a JSON blob with a Python Flask app, your app also just breaks on that input.
- tgsovlerkhgsel 5y agotry: 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.
- andrewmcwatters 5y agoWhat solution? There is no solution. The web just works that way. You receive some bytes and you do stuff with them. Any other expectation is a farce. Is a property missing after serialization? Can you even serialize it? Maybe a different status code returns a different mime type! OK, whatever. That’s not always an error, nor is it remotely “exceptional.”
- tptacek 5y agoI mean, I agree. That's why I'm sort of confused about what the problem is here. Yes, you can get unreliable inputs. Most apps barf on them, even if they think they don't. The barfing mechanism is pretty much the same everywhere.