-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tell user which variable caused error when quantifying #42
Comments
error reporting is a good point. However, I'm not a big fan of these unpacked comprehensions (which technically are not equivalent), so I'd like to find a way to keep the comprehension while still getting an error that is informative enough. Unless we want to add a As for the failure, |
Thank you! I knew it was going to be something silly.
Why? This comprehension goes over 4 lines, and (in my opinion) is not particularly easy to understand. What's the advantage of not unpacking it?
It seems like it would be bad practice to pass a variable into a function for the sole purpose of keeping track of the context from which that function was called. |
I usually find comprehensions easier to read: there's only a single place to look for a description of the new values or a list of the applied filters. Of course, comprehensions can be written in a way that makes it harder to read. Would it help if we assign a name to the result of the The technical difference between both options is that while the comprehension will collect all items and only then create the new container, in the loop the container will have to grow on each assignment because it doesn't know the total number of elements. Python will work around that by allocating more than is necessary, which means that there's less of an overhead. However, we don't expect users to have a lot of variables (I didn't measure, but I would guess this is not much of an issue with less than a hundred elements) which makes this discussion a matter of taste.
exactly, which is why I am trying to find a better way. I'm not sure there is one, though. |
Yeah fair enough. Even just changing some variable names would help, e.g. possible_new_units = zip_mappings(units, unit_attrs)
new_units = {
name: _decide_units(unit, registry, attr)
for name, (unit, attr) in possible_new_units.items()
if (unit and attr) is not None
}
Yes because of the generator underlying the comprehension, right. But I agree this doesn't really matter - the largest datasets I've ever seen still only have ~70 variables.
I was trying to find out whether catching then immediately re-raising with context added is "acceptable" or not. I think it's fine to do this possible_new_units = zip_mappings(units, unit_attrs)
new_units = {}
for name, (unit, attr) in possible_new_units.items():
if unit is not None or attr is not None:
try:
new_units[name] = _decide_units(unit, registry, attr)
except Exception as e:
raise ValueError(f"Failed to assign units to variable {name}") from e which then means instead of just this non-variable-specific error
you get this bit appended to the end
This could be even clearer: However, this messes up a couple of tests because then a less specific error gets raised as the final one instead of say |
That sounds good. Maybe it would be easier to raise the same type of exception as the one we catch? Something like this: try:
new_units[name] = _decide_units(unit, registry, attr)
except Exception as e:
if not isinstance(e, (TypeError, pint.errors.UndefinedUnitError)):
raise
raise type(e)(f"Failed to assign units to variable {name}: {e}") from e We probably wouldn't even have to care about filtering out other errors (not that I would expect any). Not sure about trying to find out if the unit came from the attribute or if it was passed to |
Raising the same type of error seems like the best solution to me - then tests would only break if they were expecting a specific error message rather than a specific error type. I'm kind of worried this is like horrible practice or something but I can't really see a better way to do it. There's also probably no point trying to filter anything in that case.
I suppose really the user should know which of these two cases it was based on their input. I'll submit a PR then. |
While debugging the error caused by #40 , I found that if pint throws an error whilst quantifying one variable in a dataset, then
ds.pint.quantify
throws that error without telling your which variable caused it. This is not very helpful for the the user who is trying to convert their xarray data to be pint-backed, it would be much better if the exception were caught and re-raised, something like thisI tried to implement this, but got stuck when trying to unpack the dictionary comprehension here
pint-xarray/pint_xarray/accessors.py
Lines 501 to 505 in 62c15c5
I'm probably just being dumb, but how exactly is this unpacked loop + condition different from the original dictionary comprehension?
The latter causes test failures but the former doesn't...
The text was updated successfully, but these errors were encountered: