Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
What is a good way to add extra information to a Python exception
For example
I have nested dictionaries as so
d = {'Bob':{'lastname':'Smith'}, 'Sally':{}}
if I access the dictionary like this I get what I want which is the last name
name = 'Bob'
value = 'lastname'
print(d[name][value])
Smith
If I try accessing Sally's last name I also get what I want which is an KeyError
name = 'Sally'
value = 'lastname'
print(d[name][value])
KeyError: 'lastname'
However my issue is that this exception is extremely undescriptive so my code now looks like this
try:
name = 'Sally'
value = 'lastname'
print(d[name][value])
except KeyError:
raise KeyError("{0} has no {1}".format(name, value))
KeyError: Sally has no lastname
This is gives me the descriptive error I'm looking for but I'm left wondering if this implementation is pythonic. Is there a better way to express this? I have tried looking through the python documentation and other common packages but found nothing conclusive that at least I could see
Let's just lay it out there and see where that takes us. But first, look into Jeff Knupp's article on this topic. It may be a review, but there are great little nuggets in there.
Consider the LBYL (look before you leap - see the article) approach:
if name not in d:
raise KeyError('{0} is not in first level of dict'.format(name))
if value not in d[name]:
raise KeyError('{0} is not in second level of {1}-dict'.format(value, name))
versus the EAFP (easier to ask forgiveness than permission - again, see the article) approach:
try:
lastnames = d[name]
except KeyError:
raise KeyError('{0} is not in the first level of dict'.format(name))
try:
person = lastnames[value]
except KeyError:
raise KeyError('{0} is not in the second level of {1}-dict'.format(value, name))
Now, consider the Zen of Python. In my opinion, the former approach is both more "beautiful" and "simpler." It also strikes me as more "readable," albeit only by a thin margin for this case. On the other hand, the latter is more "explicit" in that it clearly delineates the possibility of failure and how to handle such cases. Furthermore, if you ever need to expand the activities around the error handling, the "practicality" of the EAFP approach should not be ignored; should you need it, the power and convenience of the full try: except: else: finally clause is not to be underestimated. Having said this, I personally gravitate towards your try: except: solution.
However, it is perhaps more important to trust your gut. If you are conscientious enough to be thinking about these things even in simple cases, you will catch yourself in the truly tricky situations where you really ought to be considering an alternative or more pythonic approach.
Don't mind me. It's an opinion, after all.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have a lot of assert statements I use to validate input data and state of the program. ie :
assert all((i.children is not None for i in items)), "Someone has no children."
I would like to use the same syntax but using specific Exception, ie:
if any((i.children is None for i in items)):
raise NoChildrenException("Someone has no children.")
Is there a one line syntax to achieve the same?
I tried :
if any((i.children is None for i in items)): raise NoChildrenException("Someone has no children.")
but that's not PEP8 valid.
or
def raise_if(condition, clazz, *args):
if condition:
raise(clazz(*args))
raise_if(any((i.children is None for i in items)), NoChildrenException, "Someone has no children.")
but that's a bit ugly.
UPDATE:
Thanks #Thomas. I fixed the examples in the problem description.
I think the closest to what I want to achieve is this one (based on #puchal's answer).
def raise_exc(exc):
raise exc
all((i.children is not None for i in items) or raise_exc(NoChildrenException("Someone has no children."))
I haven't thought about using or in this way.
Currently there is no way to do this that is also valid PEP8.
It doesn't get more pythonic than this:
if any(i.children is None for i in items):
raise NoChildrenException("Someone has no children.")
Note you have an error in your problem description - you have to negate the condition in your second code example. You can get rid of the two not by using any() like shown above.
There is no way to do it ellegantly.
I think the closest way to achieve it would be:
def raise_exc(clazz, msg=""):
raise clazz(msg)
all((i.children is not None for i in items)) or raise_exc(NoChildrenException, 'message')
The "correct" way to do this is without assert at all.
if any(i.children is None for i in items):
raise ValueError("Someone has no children") # Or whatever exception you feel is appropriate
In Python 3.8, you can capture which item had no children in the same line.
if any((childless:=i).children is None for i in items):
raise ValueError("%r is childless" % (childless,))
(The assignment expression operator := creates a variable in the scope where the generator expression is defined, not one local to the generator expression itself.)
Your second snippet is the most pythonic IMHO.
When I have to add a lot of validation rules I usually do something like this:
checks = {
lambda items: any(i.children is None for i in items): NoChildrenException("Someone has no children."),
lambda items: any(i.children.age >= 18 for i in items): AdultChildrenException("Someone has an adult children."),
lambda items: not bool(items): NoItemsException("No items given."),
}
for condition, exc in checks.items():
if condition(items):
raise exc
Moving all the checks (eventually having bigger functions instead of lambdas) in a separate .py file "validations.py".
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I want to get your feedback on which of the two snippets is the more pythonic way to handle a lookup.
I'm developing a wrapper for an XML File. I'm loading the XML file, parsing it, store the content in a dictionary and then allow the access through a class method.
Specifically - if the a given returns no result, should I return None or raise an (Key)Error?
I'm a bit confused, because some people suggested me to throw an Error instead of returning an empty value. They said it would be easier and clearer to handle then the error no a higher level.
This is a simplified version of the code:
class NoResult(KeyError):
pass
class Wrapper(object):
....
self.my_dict = {}
....
get_Entity(self, id):
if id in self.my_dict:
value = self.my_dict[id]
return value
else:
return None
class Wrapper(object):
....
self.my_dict = {}
....
get_Entity(self, id):
if id in self.my_dict:
value = self.my_dict[id]
return value
else:
throw NoResult
I would really appreciate your thoughts!
The latter matches what you would expect with standard Python types, and can be simplified to:
def get_Entity(self, id):
return self.my_dict[id]
This will raise the KeyError for you if id isn't in self.my_dict. Getting an error tells the calling function that what was expected to be in the dictionary wasn't - quietly returning None leaves you open to subtle bugs later (unless you immediately check if val is None, in which case you could have used try anyway).
(The other version can also be simplified, to:
def get_Entity(self, id):
return self.my_dict.get(id)
).
dict already contains the 2 behaviors. (get -> None and [] -> KeyError).
Also, None is a valid value for a dict:
my_dict = {'key': None}
my_dict['key']
# Returns None
Ok, this will be a little bit generic but looks at the expectations of the programmer using your library. If I am doing a lookup in an XML file I am probably expecting that I will get a result.
Lets say I am then a lazy programmer who does no validation of what you return to me and try and use it. If you return to me a special none value my code will continue to run and will encounter an error later and it may not be obvious to me that that is the root cause.
On the other hand if you threw an exception as soon as I requested the invalid value my program would crash immediately and give me an accurate explanation of what went wrong.
If programmers all did careful validation on what your library returns either way will work fine but lazier (read most :P) programmers will likely not do so, thus the exception route will provide the least surprise and confusion. As a library you never want to surprise or confuse your user when avoidable so I would go for the exception route.
However I shall quickly note, if doing an invalid lookup is a 'normal' action in your libraries work-flow you can more reasonably expect programmers to check so then either becomes reasonable.
Remember the rule of thumb, use an exception when the action is actually exceptional and surprising, otherwise ymmv but you probably dont have to.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I'm trying to be quite strict about PEP8 coding style, but this question has not been answered for me. These are two versions of the same code, one is using temporary variables of which each is used only once, the other version doesn't use temporary variables and looks more like what would be common in functional languages.
For me the functional one looks prettier, but I'm not sure if there is any guideline about how many functions I should chain together.
Version with temporary variables:
class EmailConfirmation():
#receiver(email_confirmed)
def confirmed(sender, **kwargs):
email = kwargs['email_address'].email
keystone_id = User.objects.get_by_natural_key(email).keystone_id
client = Client(token=settings.KEYSTONE_TOKEN,
endpoint=settings.KEYSTONE_URL)
client.users.update(keystone_id, enabled=True)
Version without temporary variables:
class EmailConfirmation():
#receiver(email_confirmed)
def confirmed(sender, **kwargs):
Client(
token=settings.KEYSTONE_TOKEN,
endpoint=settings.KEYSTONE_URL
).users.update(
User.objects.get_by_natural_key(
kwargs['email_address'].email
).keystone_id, enabled=True
)
Is there any guideline that defines which of these two versions is recommended, or are both ok?
The first version should be preferred. This is true, not just for Python, but for other languages like C++/Java because its prone to error and per the Zen of Python Errors should never pass silently., which would be the case in your second version.
The Reason:
Consider, the instantiate of Client fails, which results in returning None. Chaining the same object without checking for a success or proper error handling would result in errors unrelated to the actual problem AttributeError: 'NoneType' object has no attribute 'users'.
So it is always better, to avoid chaining objects, as that would cause errors to pass silently.
Example
Consider the following modification to your first version
class EmailConfirmation():
#receiver(email_confirmed)
def confirmed(sender, **kwargs):
email = kwargs['email_address'].email
keystone_id = User.objects.get_by_natural_key(email).keystone_id
try:
client = Client(token=settings.KEYSTONE_TOKEN,
endpoint=settings.KEYSTONE_URL)
except CustomClientError as e:
# Your Error Handling Code goes here
raise CustomClientError("Your Error Message")
else:
if client.users:
client.users.update(keystone_id, enabled=True)
else:
raise CustomEmailError("Your Error Message")
finally:
# Cleanup code goes here
PEP8 doesn't dictate whether or not to use temporary variables.
To my eyes, though, the second version does not look very Pythonic: most Python code avoids chaining methods like that. I might even store the User rather than the keystone_id:
user = User.objects.get_by_natural_key(email)
client = Client(token=settings.KEYSTONE_TOKEN,
endpoint=settings.KEYSTONE_URL)
client.users.update(user.keystone_id, enabled=True)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python FAQ: “How fast are exceptions?”
I remember reading that Python implements a "Better to seek forgiveness than to ask permission" philosophy with regards to exceptions. According to the author, this meant Python code should use a lot of try - except clauses, rather than trying to determine ahead of time if you were about to do something that would cause an exception.
I just wrote some try - except clauses on my web app in which an exception will be raised most of the time the code is run. So, in this case, raising and catching an exception will be the norm. Is this bad from an efficiency point of view? I also remember someone telling me that catching a raised exception has a large performance overhead.
Is it unnecessarily inefficient to use try - except clauses in which you expect an exception to be raised and caught almost all of the time?
Here's the code -- its using the Django ORM to check for objects that associate users with various third party social providers.
try:
fb_social_auth = UserSocialAuth.objects.get(user=self, provider='facebook')
user_dict['facebook_id'] = fb_social_auth.uid
except ObjectDoesNotExist:
user_dict['facebook_id'] = None
try:
fs_social_auth = UserSocialAuth.objects.get(user=self, provider='foursquare')
user_dict['foursquare_id'] = fs_social_auth.uid
except ObjectDoesNotExist:
user_dict['foursquare_id'] = None
try:
tw_social_auth = UserSocialAuth.objects.get(user=self, provider='twitter')
user_dict['twitter_id'] = tw_social_auth.uid
except ObjectDoesNotExist:
user_dict['twitter_id'] = None
The first one will rarely take the exception, since right now we are enforcing "Sign In With Facebook" as the primary method for new users to join the site. But, Twitter and Foursquare are optional, in case they want to import friends or followers, and I expect most people will not.
I'm open to better ways to code this logic.
Whenever you code there is a balancing of concerns: performance, readability, correctness, extendability, maintainability, etc.
Unfortunately, it is often not possible to improve code in each of these directions at the same time. What is fast may not be as readable for instance.
One of the reasons why try..except is encouraged in Python is because you often can not anticipate all the ways your code may be used, so rather than checking if a specific condition exists, it is more general to just catch any of a certain class of error that might arise. Thus try..except may make your code more reusable.
However, it is also true that try..except is slow if the except clause is often being reached.
Is there a way to code that block so that an exception is not being raised and use try..except to catch the less frequent condition?
Or if not, for the sake of efficiency, you may choose not to use try..except. There are few hard and fast rules in programming. You have to choose your way based on your balance of concerns.
If you are attempting to optimize this function for speed, you should focus on what is likely to be the actual bottleneck. Your three database queries, each of which will cause the operating system to context switch, almost certainly take an order of magnitude longer than catching an exception. If you want to make the code as fast as possible, begin by combining all three database queries into one:
auth_objects = UserSocialAuth.objects.filter(user=self, provider__in=('facebook', 'foursquare', 'twitter'))
and then loop through the objects. The provider__in filter may be unnecessary if those three providers are the only ones in the database.
It's true that catching an exception is moderately expensive (see below for some timings) and you wouldn't want to this it in the bottleneck of your program, but in the examples you give, catching the exception is going to be a very small part of the runtime in comparison with the call to Model.objects.get which has to build a SQL query, transmit it to the database server, and wait for the database to report that there's no such object.
Some example timings. Function f2 throws and catches an exception, while f1 implements the same functionality without using exceptions.
d = dict()
def f1():
if 0 in d: return d[0]
else: return None
def f2():
try: return d[0]
except KeyError: return None
>>> timeit(f1)
0.25134801864624023
>>> timeit(f2)
2.4589600563049316
And f3 tries to get a non-existent object from the database (which is running on the same machine) via Django's ORM:
def f3():
try:
MyModel.objects.get(id=999999)
except MyModel.DoesNotExist:
pass
This takes about 400 times longer than f2 (so long that I didn't want to wait for the default number=1000000 iterations to complete):
>>> timeit(f3, number=1000)
1.0703678131103516
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I am trying to improve my program so that it conforms to good programming
practices. So I am looking for suggestions on whether the way I have programmed
something is a good way of doing it.
I have a module called dbfunctions.py in which I have defined:
dbparams = {
'dbname': 'qualitysimparams',
'tablename': 'qualityparams',
'tablecols': ('numpeople', 'numreviews', 'prophunters',
'utility_funcform', 'goods'
)
and a function:
def obtainid_ifrecord(dbname, tablename, tablecols, values):
'''Checks if there already exists a record with given <values>.
If so, returns the id of that record, otherwise returns zero.'''
con, c = connecttodb()
q1 = "use {0}".format(dbname)
c.execute(q1)
q2p1 = "select id from {0} ".format(tablename)
q2p2 = "where " + " = %s and ".join(tablecols) + " = %s"
q2 = q2p1 + q2p2
c.execute(q2, values)
res = c.fetchall()
c.close()
con.close()
if res:
return res[-1][0]
else:
return 0
There are other functions and variables in addition to the above two, but
they are not relevant for this post.
In another file I have a function:
def checkif_paramcomboexists(numpeople, numreviews, prophunters,
utility_funcform, goods):
'''Check in the database if the simulation has been run with the
specified parameters. If so return the id of that run.
'''
goodsjson = sjson.dumps(goods)
# paramvalues: in same order as listed in dbf.dbparams['tablecols']
paramvalues = (numpeople, numreviews, prophunters,
utility_funcform, goodsjson)
id = dbf.obtainid_ifrecord(dbf.dbparams['dbname'],
dbf.dbparams['tablename'],
dbf.dbparams['tablecols'],
paramvalues)
return id
It seems to me that the fact that hardcoding the variable names in the
paramvalues variable in function checkif_paramcomboexists is not a good practice.
If later I change the order of variables in dbfunctions.dbparams['tablecols'] for any
reason, checkif_paramcomboexists function will fail (and can fail silently depending
on the data types). One way to get around this is to define:
paramvalues = [eval(x) for x in dbf.dbparams['tablecols']]
But I have heard that generally it is a bad practice to use eval (although I do not know
why and when it is okay to use it). My questions are:
(i) Is it okay the way I have coded this in regards to the concern I have? I think the answer
is 'No', but just want to check with the experts here.
(ii) Is use of eval as I have indicated an acceptable solution?
(iii) If answer to (ii) is 'no', what is the alternative?
Thank you for reading through this.
You're right about the hardcoding not being great, and definitely stay away from eval. If you don't want to use *args or **kwargs (which are really better options, by the way), you can use the inspect module to do what you're trying to do.
import inspect, collections
def checkif_paramcomboexists(numpeople, numreviews, prophunters,
utility_funcform, goods):
...
temp = inspect.getargvalues(inspect.currentframe())
args = temp[0]
valuedict = temp[-1]
ordered_args_dict = collections.OrderedDict(sorted(valuedict.items(), key=lambda x: args.index(x[0])))
paramvalues = ordered_args_dict.values()
...
Basically, what's going on here is that inspect.getargvalues(inspect.currentframe()) gets you an object where the first item is a properly ordered list of the argument names and the last item is a dictionary of the argument names and values. We then create an ordered dictionary by grabbing the argument name/value mapping from the dictionary, and ordering it based on the list order.
What you end up with is an OrderedDict that has all of the arguments with their values, but also has them in the right order. That way, you can still choose to refer to them by name (e.g., ordered_args_dict['numpeople']), but if you can still get all the values in order as you wanted with ordered_args_dict.values(), which will give you the output you're looking for for paramvalues: a properly ordered list of the arguments, no matter what the name is.
This situation really calls for an object. You are duplicating what is essentially instance information about a specific database table in 2 places, so it would make sense to make both these functions in to methods of some sort of database table interface object that has a tablecols attribute, then use self.tablecols in both methods.