 So the next stock is Python Traceback for humans and the speaker for today is Anand Reddy Pandy Kuntah So about the speaker The speaker is a well-known Python developer and today's talk is focused for on Python Traceback for humans I request Anand to kindly Initiate that session Okay, it might take for him two minutes. So anyone wants to you know Tell a joke or something you are very much welcomed on the dice Any joker in here joker. I mean joker. Yeah, I'm coming Okay Hello Is it audible at the end? Yeah, font size is visible Yeah, good so This session is mostly about trace back and debugging code and stuff like that So, how many of you seen Python trace back or errors? Oh, very good. So everybody has seen so whenever your code has some errors So python will throw some exception and it shows some trace back So what we can do is actually we can take out whatever trace back python is giving and we can bring our own trace back And we can plug it in there. So how many of you know that we can actually do that Oh, okay, that is quite good number. So, how many of you actually tried that? Oh Oh, that's cool. So in this session, we will try to do that Okay So we'll mostly see what is a trace back and then we try to take away the default trace back and replace it with the Color trace back and then we can see what are some useful things we can do with a custom trace back And then we can see how we can customize the trace back To debug our code and lastly we will see how we can write better code to get better trace back Sounds good Yeah, let's get started So I'm just going to write a simple function called you Which attacks two arguments x and y and then returns x by y so And i'm going to write one more function called foo which attacks two arguments and just calls d of x comma y Now i'm just going to call foo with arguments one comma one So is it visible at the end? Okay, just a second Yeah, yeah Yeah, so can somebody tell me if I execute what will be the output? One are you sure? Nothing. Yeah, exactly. So somebody is not sleeping. I think So actually I need to put a print statement. Otherwise it will not Show that value So now can somebody tell me what will be the output? Yeah, let's execute and see that So Ah I'll just increase the font size So it's actually one So now what i'm going to do? I'll just call the same function But I will just call You pass arguments as one and zero Now can somebody tell me what will be the output? Huh Zero division error. Are you sure? Okay Ah, okay, it is actually throwing zero division error So as you can see here, this is this entire thing is trace back And this is the error type and this is the error message So this trace back has three frames. This is the first frame. This is second and this is the third So first we are calling print foo of one by zero Which is calling this written div of x comma y And in that it is executing written x by y where the actual error is occurring So Okay, so this line of code. This is what triggered the actual error But the actual error has occurred at this line Which is written x by y Okay, but this is the default trace back which is printed by python So now We will try to remove that error So for that what so can somebody tell me how I can remove that error Okay Try catch okay two more any more solutions. I just need to get rid of that error. That's it That we are already doing that right before that I need to have that foo of one comma zero, but still I need to get rid of that error Keep why no, I need one by zero. That's what I'm saying So what I'm going to do is I'm going to take away python exception. So I'm going to define a custom function called custom trace back Which it takes error exception type exception value and trace back And does nothing And then I'm going to Hook that function To system dot accept hook Let me import that Cis yep Now if I go back and execute see The error has just disappeared But if you see my code That One by zero is still there So what is happening here? Anybody any wild guess? Yeah, exactly. So whenever some error happens python calls system dot accept hook Which will have some custom function which prints that trace back So what I'm doing here. I'm defining a function called a custom trace back But it is doing nothing and I have hooked that function to system dot accept hook So now No matter whatever error you have your program will execute successfully So if you are in college and you are doing some demo or viva and You can just show this to your professor. So You will always get expected results with this kind of code Okay But the thing is We can't Debug the code like this, right? So what I'm going to do now is I'm going to print the actual trace back what python is printing So I'm using a function called format exception From trace back module and I will just pass the same arguments And then I'm just going to print that trace back Oh, you need to import trace back module If you see We are getting the division error again But the thing is that trace back whatever it is printing it is not being printed by python But we are writing a custom function to print that So I can print whatever I want here and I can even customize it So for example, I can just go here and I can say This is custom trace back And if I go and execute you can see Here there is a that line is printed here So right now python is not controlling the trace back, but we are controlling and we are modifying As per our needs So we have done this we are trying to mimic the python trace back Now we'll do something cool So there is a Package called pigments. So which does the syntax highlighting for a given piece of code So I'm just going to call that function So it has a function called highlight which takes Code and some formators and just highlights the given code So previously I was directly printing the trace back But now I am passing the trace back to a function called highlight Which takes the trace back and then it needs a lecture to format the code Since I'm printing a trace back. I'm giving python trace back lecture And since I'm running the program in terminal. I am giving a terminal formator so If I go ahead and run this Can you spot the difference between previous thing and this Yeah, what is the difference? Color trace back. So we are actually trying to customize the trace back So To make it better and to debug our code quickly So this is one thing we can do So can somebody tell Are there any users of customizing a trace back? Why do we need to actually customize this trace back, right? We can just use the python trace back Why do we need all this customization? Okay, like color trace back. Yeah, okay. That is one use case any others With the normal trace back also you can get right Yeah, we can make it more human readable And Yeah, exactly And any others? Yeah, yeah Yeah, yeah, yeah, so we can do lots of cool stuff by customizing the trace back So this is a color trace back So hyperlinks in ids. So for example If I have some error here And if I try to execute this code If you see here this trace back it has a hyperlink So the guy who has designed this thing he has actually taking the python trace back And wherever there is a frame and a path he is actually hyperlinking that particular path to exact file and location If I actually click this So see it actually takes me to the position where the error has occurred So this is one use case of this gwabs so Anybody have you done g y programming with python? so Yeah So whenever you are running some g y apps you just run one main loop which runs forever And that will run entire app. So when you are running an app and some exception occurs You don't want your app to crash So what they will do they will run one main loop and whenever some exception occurs Instead of throwing the trace back they will silently lock that error somewhere else and they will continue execution of main loop So by that way even though some error occurs the whatever g y that is there it won't crash It will be it will keep running on So that is one more use case and Ah work zig so how many of you do web development? How many of you used work zig? So so what will be the use of this? So what we can do is here we can go to each and every frame and we can debug actually So if you see here, I have some trace back here But the thing is it provides interactive debugging for example here one frame is there I can go to this frame and then I can just say inspect locals So it prints all the locals which are present in that frame And I can go to some other frame where I think error might be happening and I can debug there also But you can't do the this in the terminal here since the state of each and every frame is saved We can inspect each and every frame wherever we want. So for interactive debugging This will be very useful So debugging tool so I have Simple notebook here So we need to We'll do we'll take the trace back and we'll inspect and see what are all the items that are present in the trace back So i'm just importing the function foo which we have defined earlier Okay, the function is imported Now i'm Can you see the font? Is it visible at the end? Yeah now Not visible Now i'm trying to run the same function with the same arguments, but i'm trying to run that in try accept block So i'm trying to execute foo of 1 comma 0 and if some error exception occurs i'm storing the exception values in at In three variables. So there is one function called assist dot accept info So whenever an exception occurs that function has all the exception information So whatever it is written i'm just storing in three variables And if i try to format and see what is present there So the same thing it is present So the exact error it is showing that it has called foo and then It has called a written div of x by y and it is returning x by y which is throwing zero division error So now we have three variables, which is nothing but exception type and then exception value and trace back So this exception type is nothing but zero division error and the exception value is division by zero error And we have this interesting object, which is nothing but a trace back object So now we will try to see what is present inside that So there is one function called a get inner frames, which is present in inspect module When you pass a trace back object to that function it returns all the inner frames that are present in the trace back So it is returning all the three frames and if i see what is present in first in the second frame It has actually a frame object And then it is showing the complete path and then it is showing the line number which is present And it is showing the function where it the error has occurred and it is showing the line where it has occurred So i'm just going to unpack that frame record And now i have all the frame frame name line number everything And now i'm going to pass this frame to A function called a get arc values What this function does is it takes a frame object and gives all the values that are present in that frame so You see it is actually printing what are all the arguments that are passed to the function We have passed two arguments, right? So it is giving x and y And where are we have not passed any optional arguments? So it is returning none and we have not passed any keyword arguments So it is also none and it is even showing local variables. This is this will be very useful actually So the local variables it is showing x and y x is one and y is zero So we can actually pass the frame and local variables to a function called scan wires Which actually takes a piece of code and tokenizes the Code and finds the variable in it and actually returns the value of that variables So So In the line where the error has occurred it is a return div of x by y The frame we have taken so if we look at the object it has returned It has returned a div which is nothing but a global variable and it is a function And it has returned the x which is the local value and its value is one and y which is the local value which is zero So What we have done so far now is we have taken the trace back object whenever an exception occurred And we are going to inner frames and we are inspecting what are all the variables that are present in that frame In addition to that Whenever some error occurs we are trying to find the variables in that line and we are trying to get the values Back here Now i'm going to show one function So I have A small Code here So i'm just importing a module called num and i'm getting three numbers from that Module and i'm trying to sum the three numbers i'm trying to print the total So if i execute that it should print a total right? So i'm just going To run that function So it is throwing some error So it is throwing type error unsupported operand types for int and stir So can somebody tell me how to debug this? So replace No, we need to get the total right how to Hmm Check the type of that three numbers and then do typecasting. Okay, so Remember the procedure we are doing we are trying to Okay, we are trying to check the type of all this and So it is showing the first is int second is string and the third is int So I need to go back to my script and then I need to typecast these two Int and I need to remove this print statement Now if I go back and execute it is running successfully, right? So this is one way of debugging that code No, actually that is a module it is returning It is some third party module So it is like whenever When you are writing some real life code, you won't have like everything up and running You will be calling some other functions and somewhere you are retaining some data and somewhere you might be doing something else So there is a good chance of you getting that type error So where you might have to do typecasting, but you can't change the upstream where that error is coming So in such situations so What you can do is We can actually print So whatever we have seen in the notebook. I have already packaged that into a simple package called ptb And if I just import that module and I enable that And if I execute that module So now also we are getting the same error But if we look at that trace back So it is showing that the error has occurred in this particular line Where total equal to num1 plus num2 plus num3 But the interesting thing is just below that line it is automatically printing all the values of the numbers So it is printing that num1 is 1, num2 is string 2, num3 is 3 So we don't need to actually go back to our script and then put one print statement and then again Come back and execute and all this So just by looking at that trace back we know the value of the objects So we can just go back and do typecasting So which will be a bit easier It will be useful only when you are dealing with some kind of errors, but yeah, it will be useful So filtering frames So How many of you use Django here? Okay, so have you seen Django trace back? So one of the interesting thing with Django trace back is so here I have some If you look at the frames here, this frame is actually dimmed This is dimmed, this is dimmed, this is dimmed, but this frame and this frame are actually highlighted So the reason why Django does that is This whatever frames that are present here, they are part of core Django So most likely the error will not be present there So Django tries to dim that frames to make it easy for the user to find the bugs So actually the error is somewhere here So just by looking at that trace back, we can Get an idea that the error will be present only in that these frames So When we were actually getting the frame information If we see the frame record, we actually have the frame path here So what we can do is whenever we are printing a trace back We can actually take the frame path and we can check with the standard library path And if it is present in that we can dim the frame if it is not present We can actually highlight or do something else with that frame So it helps to distinguish between multiple frames More context So how many of you use ipython? Yeah, so if you have used ipython When you run some program which has some error Let me run some function So see Let me run the same thing in So when I run function using Normal python Whenever an error occurs it actually shows the line where the error has occurred or For each and every frame the function or the line which has caused the error It shows only that line But if you look in ipython, it actually shows Two lines before where the error has occurred and two lines after also So it does the same thing for each and every frame When you are doing some kind of numerical or scientific computation you might be getting errors Because of previous lines also you might be doing some subtraction It might be giving some zero or something else So when you have some more context where the error is occurring It might be easy for you to identify the error So this is one of the use case So we have been doing all these things like magical print whenever some error occurs Print some variables and then we are doing filtering frames and then We are looking at the context and we are doing lots of other things So do you think is it really worth spending time on doing all of this stuff? Yes So to decide whether it is worth or not, we'll let's have a simple exercise I'm just going to show you a picture Which has number five and number two You just need to count number of number twos in that picture Get it? Just count number of twos I'm just going to give you 10 seconds Okay, let's start Time up time up Six five four Four five six. I'm hearing only these three answers Ah, okay. Okay. I got it. I got it. But you took around more than five seconds So all most of you took more than five seconds to figure that out So I'm going to show you one more slide. Just tell me how many of them are there I have actually highlighted all the twos for you And again you are counting So actually in the previous slide it is quite difficult, right? You can't make out where the twos are But when you differentiate you can actually easily see That is the thing we are doing with the filtering frames So actually whenever we are trying to make the things like that it will be quite useful and We do spend a Good amount of time on debugging our code So it will be and the thing is it is only like one time investment We just customize the trace back like whatever you need and it will be there forever. So It will be quite useful So Now let's see So one or two tips on writing Some code which will give us some better trace back So what you can do is actually whenever you are writing code you can use some custom conditionals and custom exceptions To catch the errors. For example, when you are opening a file You can just actually the the file path might not be correct or there might be some typos like that So there is good chance of that file might not be found there So what you can do is when you are trying to do some task like that you can actually catch the exceptions which might occur in that case and Even when you are trying to Build some apps which will be used by users and some exception occurs You don't want to show the trace back to Users, right? So you need to give them some meaningful message so that they can understand better. So Here I have a small script which reads an integer So if I execute that So it is just asking For enter an integer instead of entering an integer if I just type some string or something like that It just throws some weird trace back If you are actually shipping this code to some user who is not a developer This might actually confuse them a lot, right? So what you can do is you can just catch that error and you can display them a good message So now if I enter some String or something like that it just says please enter integer only So and if I enter integer it shows congratulations. You have successfully entered an integer so The thing is you you need you don't need to show that trace back and everything to end users Chaining exceptions. So how many of you use python 3? python 3 Okay, only a few hands. Okay Have a small code I'm just using python 2 here So What I'm trying to do here is I just defined a function called compute Which it tries to divide a number with another number And when an exception occurs I am trying to log that exception in a file called log file.txt I'm just taking the exception and I'm trying to write the exception to a file And what I'm trying to do I'm just calling the compute of 1 by 0 So what will happen when I call compute of 1 by 0 it goes here and it tries to execute this And whenever this happens so it will throw 0 division error. So it tries to log that error So when it tries to log the error as mentioned here that log file is actually not present So it will throw one more exception If I run this It just gives me some error called IO error file not found What I'm actually trying to do here is trying to divide 1 by 0 I'm getting an error called IO error file not found This is happening because when I am trying to divide 1 by 0 I'm getting 0 division error And I'm trying to handle the 0 division error by logging it into a file And when I'm logging that into a file I'm getting an exception here So this exception is getting lost and this exception is getting printed So it will be difficult for developers to figure it what is actually happening But if I execute the same code in python 3 See it actually shows 0 division error here 0 division error 0 division by error And then it displays message during handling of above exception another exception occurred And then it is showing that file not found error So python 3 actually does exception chaining implicitly So whenever one error occurs and you are trying to handle error and some other error occurs python 3 actually tries to chain the exceptions and print it If you want you can actually try to manually also you can rise the exceptions Rise some error from other error like that So you can do lots of stuff with python 3 So try to read that pep 3 1 3 4 So it teaches about python exception handling and how it does implicit exception chaining So if you are very lazy to do that error, please start using python 3 So the thing is you don't need to stick to whatever trace back python is giving You can actually customize the trace back according to your needs And whenever you are getting a trace back you can remove all unnecessary information And you can take out whatever information that is required for you So that's it if we have time for questions I will take otherwise I will take out So he is asking like when i python is showing a lot of context right Where error has occurred two lines before and two lines after So let me just So you can see here here we have only one line where the error is occurring in the frame record If I go back here here when we are calling get in our frames in addition to trace back We can also pass context if I give context equal to 5 and then execute And then look at the frame record now you can see you are getting actually five lines Previously you are actually getting one line so whenever you are calling that get inner frames You can actually pass the context which you use the amount of context whatever you want Local variables so when you are when you have a frame record You are so you are calling that inspect dot get arg values So it is returning all local variables that are present in that particular frame Does that answer your question Whatever I have told I have written that into a package called ptb and I have published on pipi I think there are many other packages Any more questions two three four six guys are sleeping right now So wake them up and ask them if they have any questions Okay, thank you