Numpy-style error tracebacks? - python

In numpy, when you make a mistake, the error doesn't tell you about all the numpy internals, just the user-level error made. For example:
import numpy as np
A = np.ones([1,2])
B = np.ones([2,3])
A+B
spits back
Traceback (most recent call last):
File "/home/roderic/Desktop/scratchpad.py", line 5, in <module>
A+B
ValueError: operands could not be broadcast together with shapes (1,2) (2,3)
Notice how it doesn't tell you about all the internal bouncing around that numpy did in order to determine that you are multiplying incompatible matrices, nor where the ValueError was raised exactly. I want to do the same for my project, where the traceback should stop outside of the module internals (unless I am on debug mode). So, if the traceback is 10 steps long, and the first 4 are on user level, and the last 6 are internal processing from my library, I only want to feature the first 4.
I know how to extract the stack, but I don't know how to modify it and re-inject it before raising the exception. I also assume this is considered a bad idea, and if so, I'd like to know what my other options are.
My horrible temporary solution is looking like this:
except AssertionError as error:
# something went wrong, the input was not correct
print( "Traceback (most recent call last):")
for filepath, line_no, namespace, line in traceback.extract_stack():
if os.path.basename(filepath)=='MyModuleName.py': break
print( ' File "{filepath}", line {line_no}, in {namespace}\n'
' {line}'.format(**locals()))
exit()

The only reason that A+B doesn't show any internal stack frames is that numpy.ndarray.__add__() happens to be implemented in C, so there are no Python stack frames after the one containing the A+B to show. numpy is not doing anything special to clean up the stack trace.

Related

In Python, how can the traceback module be used to find where an exception is generated?

I'm working on a convoluted FOSS project that utilizes GTK+3. When a flow graph is generated and attempted to run it, it generates the following error:
'Page' object has no attribute 'get_flow_graph'
There are 30 different files that have the generic "...object has no attribute..." exception listed in the code, and there are 4 files that call the function get_flow_graph().
So what I want to figure out is which of the 30 files that generate that particular error message is being executed, and preferably which of the 4 files with the function are causing the error in the first place.
I'm trying to use Python's traceback module to figure out where, specifically, the exception is being generated. I think I figured out the file that is calling the function that ultimately errors out, but I can't seem to get the traceback module to provide much more.
For example, if I wrap the function like this:
try:
fg = self.page.get_flow_graph()
except Exception:
traceback.print_exc()
then I just get
File "<redacted>", line 66, in _popen
fg = self.page.get_flow_graph()
AttributeError: 'Page' object has no attribute 'get_flow_graph'
'Page' object has no attribute 'get_proc'
as the output. So I get the original exception but a new get_proc error that doesn't help me but is obviously associated with trying to use traceback.
Maybe I'm not putting the trace in the correct file/location, or maybe I'm asking too much, but how should I write it to figure out the actual stack trace for the original AttributeError?
Does using
except AttributeError as e:
print(e.__traceback__.tb_lineno)
print(e.__traceback__.tb_frame)
instead, helps you further? (really asking, not being ironic)

"where" clause in numpy-1.13 ufuncs

I occasionally use the where clause in numpy's ufuncs. For example, the following:
import numpy as np
a = np.linspace(-1, 1, 10)
np.sqrt(a, where=a>0) * (a>0)
In Numpy 1.12 and earlier, this used to give me square root values where possible and zero otherwise.
Recently, though, I upgraded to numpy 1.13. The code above now gives me the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Automatic allocation was requested for an iterator operand, and it was flagged as readable, but buffering without delayed allocation was enabled
I thought that this was exactly how the where clause was supposed to be used, but perhaps I was wrong. So I have two questions: first, what's wrong with this code; and second, what is the recommended way of achieving my goal?
For future reference: this turned out to be a bug in numpy. It has been fixed for the next numpy release, presumably version 1.13.1.
A workaround fix for 1.13.0 is to explicitly provide an out parameter to the ufunc. In the example above, np.sqrt(a, where=a>0, out=np.zeros(a.shape)) works.

Understanding a traceback error

I am trying to understand a traceback error that I am receiving. See below.
Traceback (most recent call last):
File "test.py", line 291, in test_cache_in_function
self.assertTrue("sunset" in testfilestr,"Testing that the sunset request was cached")
AssertionError: Testing that the sunset request was cached
Does the above error mean that "sunset" should not be in the cached file?
A point about nomenclature. You are getting a AssertionError. The error is printed along with the traceback, which indicates the sequence of calls that led to that error.
In your particular case, it looks like the error is caused because the assertion made by self.assertTrue(...) came out False. You are asserting that the string "sunset" is in testfilestr, but it is not. Probably because it is in the cache file instead.
The second argument to assertTrue is a message, which you see as the message to the AssertionError. This argument is optional, and is usually used to clarify the error beyond the obvious default message, which would be something to the effect of "sunset" in testfilestr is False, expected True.

Why is there different behaviour from getpwuid and getgrgid?

In Python 2.7, 3.4 and 3.5, grp.getgrgid is capable of accepting a string:
from grp import getgrgid
print(getgrgid('0'))
However, pwd.getpwuid can't do the same:
from pwd import getpwuid
print(getpwuid('0'))
Traceback (most recent call last):
File "getpwuid_test.py", line 2, in <module>
print(getpwuid('0'))
TypeError: an integer is required
This is because inside Modules/pwdmodule.c, getpwuid uses PyNumber_ParseTuple with a converter that uses PyNumber_Index to get a Python integer, and that raises an exception on failure.
However, in Modules/grpmodule.c, grp_getgrgid uses PyNumber_Long (Or PyNumber_Int for an old enough Python) as a conversion first, and as the documentation says at https://docs.python.org/3/c-api/number.html, this is the equivalent of running int(o), which can convert a string to an integer. Only then is it given to PyNumber_Index, by way of a helper function _Py_Gid_Converter
What is the reason for this difference? Is it a deliberate choice based on some history?
The behaviour of getgrgid seems more helpful, and it's odd that it doesn't apply to both functions. Is this undesirable behaviour in getgrgid or getpwuid?
The short answer is because humans are fallible and mistakes happen. Some are doozies and get noticed quickly, others are minor and can go years without detection.
Thank you for helping make Python better!

Openoffice3.1 pyuno confusing errors

I'm trying to get the sample and other sample codes i find for pyuno running with openoffice 3.1.1 and python 2.5 with no luck.
Unfortunately, pyuno does not give any clues about what goes wrong.
In [1]: import uno
In [2]: local = uno.getComponentContext()
In [3]: resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
---------------------------------------------------------------------------
com.sun.star.uno.RuntimeException Traceback (most recent call last)
/opt/openoffice.org/basis3.1/program/ in ()
com.sun.star.uno.RuntimeException: : 'tuple' object has no attribute 'getTypes', traceback follows
no traceback available
below is the output of execution of /opt/openoffice.org/basis3.1/program/officehelper.py
which basically boots the headless office instance and returns a related context object.
den#ev:/opt/openoffice.org/basis3.1/program > python officehelper.py
Traceback (most recent call last):
File "officehelper.py", line 42, in
from com.sun.star.connection import NoConnectException
File "uno.py", line 273, in _uno_import
RuntimeException = pyuno.getClass( "com.sun.star.uno.RuntimeException" )
RuntimeError: pyuno.getClass: expecting one string argument
pyuno takes only 1 argument and it hasto be a string, as defined in http://udk.openoffice.org/source/browse/udk/pyuno/source/module/pyuno_module.cxx?rev=1.14&view=markup
i could not manage to get pyuno.getClass work anyway.
any suggestions about how to get pyuno working?
In [1]: import uno
In [2]: local = uno.getComponentContext()
In [3]: resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
OOP gone wrong, imho. i know its OT, but i tried getting uno to work before, and gave up. this is pure Steve Yegge Prose (read up on http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html).
when you translate those lines into a more speakable form, they come out roughly as:
"Let 'local' be the result of calling method 'get component context' of 'uno'. Let the 'service manager' be the attribute 'service manager' of 'local'. Let 'resolver' be the result of calling the 'service manager' method 'create instance with context', using arguments 'com sun star bridge uno url resolver' and 'local'."
omg. no surprise something is wrong with a program that is so atrociously over-specific, convoluted, and self-referential while being not self-aware... you call a sub-method of 'local' and that sub-method has to be told what 'local' means? say what? hats off to the fearless developers who can cut through this. happy debugging.
ADDED:
thx for comment and points.
the pyuno problem i cannot do anything about in fact, but i encourage to persue a patient trytrytry approach with a clear deadline.
i also suggest to file an outright B.U.G. with the pyuno people (if they are in fact active—i got the impression that this was a rather silent project) because of the nonsense error message: the method in question appears to request one string argument, and it gets one, and it complains it did. this is so not helpful to the degree it becomes reasonable to declare a code fault.
in this kind of situation i often look into the sources. but you already did that, right?
i hate people to ask back ‘why do you want to do this?’ when i ask for help. however, sometimes someone (maybe you) does come up with another workable path in the process, one that does not include a solution to the particular problem, but helps to solve the superordinate one. so, if i may ask: what is the big picture?

Categories