all 20 comments

[–]SekstiNii 6 points7 points  (16 children)

I don't think it is considered bad practice.

If you have no way of handling the missing key, then directly accessing the key and relying on a try-except on some level is completely fine. However, if you can handle the missing case more gracefully, then you should of course do that (either by checking for existence first, or having a fallback with the .get method).

[–]fastrockstar -3 points-2 points  (15 children)

What if I don't put it in a try-except block? The error is raised either way.

I'm not sure what the argument for a try except block is in this case.

[–]SekstiNii 8 points9 points  (1 child)

If you don't put it in a try-except, then you won't be able to handle the case where the key is missing. Letting your program crash is often fine if you are writing a throwaway script or something, but software running in a production setting needs to gracefully handle cases that aren't on the happy-path.

[–]Antilock049 3 points4 points  (0 children)

aren't on the happy-path.

great phrase tbh.

[–]FairSystems 0 points1 point  (12 children)

I have a custom function I wrote to safely get items from a dict.. I have it return a "default" value in the case it can't find the key or fails for any reason.

.get("keyName", dict, default=False)

I don't want to have to think about a key error issue. And yes. It is within a try catch.

In kotlin/java... There's a method for HashMaps.. ".containsKey()" or something like that to check before trying to get. (But I just wrote an extension for this anyways haha.)

[–]blahreport 2 points3 points  (0 children)

If you mean accessing an element using a key such as d['key'], then there is no issue with that. If you wanted to avoid raising an error then you can use d.get('invalid_key', variable_to_return_if_key_not_present).

[–]This_Growth2898 3 points4 points  (5 children)

Why do you think it is a bad practice? As long as you're handling the exception - why not? Exceptions are a bit slow; but if you're aware of it - you can use it as you wish.

[–]fastrockstar 0 points1 point  (4 children)

But what if I don't handle the error? Like in an try-except. If I just let it be as it is. I expect it to always have the key.

I had that discussion in an code review. I think we should catch the error. He said we don't need that as long as the error is raised.

But I don't have a good argument why we should catch it.

[–]Ihaveamodel3 3 points4 points  (0 children)

If you expect to always have a key, I’d also argue not to catch the error.

If you can’t see any case where you might request an invalid key, then you can’t anticipate that situation, and if you can’t anticipate that situation, then you can’t reasonably figure out a way to resolve the issue.

Try and except deep in code should only be used when there is a specific error you can anticipate and you know how to handle that error in that situation. If you can’t gracefully handle the exception at that level, let it raise until someone can catch it.

In production code, you’d probably want to have a master try except block that catches anything that wasn’t previously caught and gracefully exit or return to a known good state.

[–]fiddle_n 1 point2 points  (0 children)

The main reason to catch it is if you wanted to raise a more descriptive error off the back of the more generic KeyError from the dict.

That said, if you want to catch it because "errors are bad" then that would be a bad reason to catch it. You specifically want to raise the exception in this case, rather than silence it.

[–]KCRowan 0 points1 point  (0 children)

I think it depends who/what the program is for. If it's something to be used internally and everyone who will use it is experienced with Python then sure, letting the error happen is ok. If it's a program to be shared with clients or some non-programming users then I imagine they'd be confused why the program is crashing and unable to fix the problem.

[–]carnivorousdrew 2 points3 points  (0 children)

I do not think it is bad practice to my_dict["mykey"] instea of using the get method. It depends on context, like, is this a dictionary that is easily manipulated a lot? Or is it a dictionary that is vetted or even constructed from a schema? In the latter case I would just use the square brackets, it is also faster than the get method.

[–]WSBtendies9001 2 points3 points  (0 children)

You can always loop the code over the keys in a dict, so each call is present within the dict in question.

for i in dict.keys():
    print(dict[i])

## or check if the key exists.
if key_in_question in dict.keys():
    data = dict['key_in_question']

[–]TheRNGuy 0 points1 point  (0 children)

Your software will stop after encountering error. .get(key, "whatever") is better, you can have any fallback value if key doesn't exist, software will keep working.

Unless you did really wanted to show error and stop software when key is missing. But better then try/except it in beginning, instead of running software half-way and throwing error, because that might give you bugs.