traceback.format_exc() will yield more info if that's what you want.
import traceback
def do_stuff():
raise Exception("test exception")
try:
do_stuff()
except Exception:
print(traceback.format_exc())
This outputs:
Traceback (most recent call last):
File "main.py", line 9, in <module>
do_stuff()
File "main.py", line 5, in do_stuff
raise Exception("test exception")
Exception: test exception
Answer from volting on Stack Overflowterminal - python3 traceback error - Unix & Linux Stack Exchange
python - Storing and printing an exception with traceback? - Stack Overflow
How can I use Try Except without hiding the stack trace?
Blender 3.6 and RebusFarm: Python Traceback error
traceback.format_exc() will yield more info if that's what you want.
import traceback
def do_stuff():
raise Exception("test exception")
try:
do_stuff()
except Exception:
print(traceback.format_exc())
This outputs:
Traceback (most recent call last):
File "main.py", line 9, in <module>
do_stuff()
File "main.py", line 5, in do_stuff
raise Exception("test exception")
Exception: test exception
Some other answer have already pointed out the traceback module.
Please notice that with print_exc, in some corner cases, you will not obtain what you would expect. In Python 2.x:
import traceback
try:
raise TypeError("Oups!")
except Exception, err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_exc()
...will display the traceback of the last exception:
Traceback (most recent call last):
File "e.py", line 7, in <module>
raise TypeError("Again !?!")
TypeError: Again !?!
If you really need to access the original traceback one solution is to cache the exception infos as returned from exc_info in a local variable and display it using print_exception:
import traceback
import sys
try:
raise TypeError("Oups!")
except Exception, err:
try:
exc_info = sys.exc_info()
# do you usefull stuff here
# (potentially raising an exception)
try:
raise TypeError("Again !?!")
except:
pass
# end of useful stuff
finally:
# Display the *original* exception
traceback.print_exception(*exc_info)
del exc_info
Producing:
Traceback (most recent call last):
File "t.py", line 6, in <module>
raise TypeError("Oups!")
TypeError: Oups!
Few pitfalls with this though:
From the doc of
sys_info:Assigning the traceback return value to a local variable in a function that is handling an exception will cause a circular reference. This will prevent anything referenced by a local variable in the same function or by the traceback from being garbage collected. [...] If you do need the traceback, make sure to delete it after use (best done with a try ... finally statement)
but, from the same doc:
Beginning with Python 2.2, such cycles are automatically reclaimed when garbage collection is enabled and they become unreachable, but it remains more efficient to avoid creating cycles.
On the other hand, by allowing you to access the traceback associated with an exception, Python 3 produce a less surprising result:
import traceback
try:
raise TypeError("Oups!")
except Exception as err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_tb(err.__traceback__)
... will display:
File "e3.py", line 4, in <module>
raise TypeError("Oups!")
Altering the default Python interpreter in a Ubuntu derived distribution is a Bad Idea. Very many system utilities expect python to resolve to the expected version and get very unhappy when it doesn't.
Better would be (obviously shell dependent):
export PATH="${HOME}/bin:${PATH}"
ln -s /usr/bin/python2.7 $HOME/bin/python
making it your default interpreter but leaving the system utilities as they expect.
added in response to comment
My first guess as to why this didn't work is that you didn't completely clean up the changes you made.
sudo rm /usr/local/bin/python
sudo apt-get install --reinstall python
Should clear up the changes you reported here and restore the distribution default Python interpreter to be the system-wide default.
Then, remove your user alias that I suggested you make above:
rm $HOME/bin/python
And check if you still get the Python traceback when a shell command is not found. If you still get the traceback, I can't think of a standard mechanism that would cause that to happen. Therefore you'll need to give us more information about what shell you are using (presumably bash) and add the output of the commands
complete | grep python
alias | grep python
python -V
to your question.
This is actually a bug in the ubuntu distribution, as discussed on stackoverflow and launchpad.
The fix is to patch your /etc/bash.bashrc file, changing the line python /usr/lib/command-not-found -- $1 to usr/lib/command-not-found -- $1.
Use the traceback module. For Python 3.10 and up, you can just write
for exc in errors:
traceback.print_exception(exc)
On previous versions, traceback.print_exception only supports the old type/value/traceback format, so you'll have to extract type(exc) and exc.__traceback__ yourself:
for exc in errors:
traceback.print_exception(type(exc), exc, exc.__traceback__)
Also, be aware that Python has a very strange way of building tracebacks, where an entry for a stack frame is added to the traceback when an exception propagates into that stack frame, rather than building the traceback all at once when the exception is created or raised.
This means that an exception's traceback stops at the point where it stopped propagating. When your the_method catches an exception, the exception's traceback will stop at the_method.
Exceptions have attributes, just like other objects in Python. You may want to explore the attributes of your exceptions. Consider the following example:
>>> try:
import some_junk_that_doesnt_exist
except Exception as error:
print(dir(error))
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', '_not_found', 'args', 'msg', 'name', 'path', 'with_traceback']
This means that for each exception in your list, you can access the exception's attribute. Thus, you can do the following:
for e in err:
print(e.args)
print(e.name)
print(e.msg)
One thing that occurs to me, though, is that the following line shouldn't really append more than one exception to your errors list:
except Exception as e:
errors.append(e)
Someone else will know better than I would, but isn't Exception always going to be one thing here (unless you're capturing multiple specific exceptions)?
I've been dealing with legacy code that uses Try Excepts. The issue I'm having is that when a failure occurs the stack trace points to the line the Except is on (well the line below that's reporting it).
Code looks a little like this:
try:
...
except Exception as e:
print(f"Error {str(repr(e))}")Is this legacy code written incorrectly? Is there a reason we don't want to stack trace?
Maybe I'm wrong and this is returning the stacktrace but in a file that I'm not looking at, but I wanted to double check because so far Excepts seem to be a hidderance for me when I'm troubleshooting.