 Hello everyone Really happy to see you all here on Friday on Europe item. It's really nice conference Do you like the conference so far? Thumbs up thumbs down. Yeah It's for me. It's my first conference outside of Bulgaria So I'm blown away by the organization by the venue by the city by the heat. No, I'm lying about the heat I'm Radoslav Georgiev. Yes, I know Eastern European names are hard to pronounce. So just call me Rado I'm Python and Django developer doing this every day and I'm also a founder of software company called hacksoft He's based in Sofia, Bulgaria. We are developing mainly with Python and Django Some Twitter GitHub whatever If you care one thing that's highly contextual for this peak is that we have an academy In Sofia where we do Python and Django courses something like nine in total so far Where we prepare people for their first job and we're quite good at this most of our students start working as Python and Django developers and I am part of the teaching team for almost all of the courses and This is highly contextual because the goal of this talk today is to share my experience and to be practical and helpful and I believe to have a lot of experience because when you're doing a course There's always and people are learning new things. There's always someone raising hand and saying nothing's working Can you take a look and you go there and you look at different people writing different kind of Python cold and At some point you start seeing the problems for two seconds in your cell you have a error here or you have an error here and While looking at a lot of cold I started seeing some patterns repeating patterns and this is actually The point of this talk to be practical to be helpful and to see different patterns in debugging not just tools I will mention tools in Python. Of course. This is your Python, but most of this will be patterns and Of course, this is by no means extensive Lecture or talk we need an entire week of debug con to cover everything about debugging It's a huge topic. So I won't be extensive. Don't hate me for not mentioning something that you are passionate about All right, I will talk about three different Things that can happen while developing any cold and for this talk Python First we will start we will start with there's an exception Everybody has seen stack traces. Everybody has seen exceptions. So we'll start with this Then we will continue at the point where nothing's happening. Nothing's working and things are starting to get frustrating and We will finish with we got our own cancer. This is maybe the worst of all. And of course, we will say some common things After all of this because there's always common things to say All right, let's start This is my beautiful boxes of frustration level When we have an exception and we start debugging it's usually not that frustrating and we'll understand why So this is level one of frustration The running example that I'm going to use because it's easy to use example here is that we have a File with some daytime intervals and call it in strings and we have a Python call that checks if there are overlapping intervals inside Not really. It doesn't really matter what I'm going to show you. This is just going to be the example and We have Yep, we have an exception And when we have an exception the first thing that we see we run the program There is an exception and we see a stack trace and stack traces are actually really really helpful This is this is a friend of the developer while developing because that traces they tell you what actually happened before you hit that exception I don't know if you have ever read stack traces front up to bottom. I love doing I love reading stack traces Unless they are like five pages of scroll then you just scroll them and don't read them at all But when people start coding they tend to not read stack traces. It's like boom exception Can you please help me something's happening? So stack traces are a friend because they contain a lot of valuable information. It's like on the bottom is the exception Valuer whatever and on the top. I don't know if you have read this But this most recent call last which means that the the first thing on the stack trace is the first function that was called and The last thing on the stack trace is the last function that was called or called executed before we hit that exception and I have some red arrows to point that To point that's the information. We have the module. We have the function name. We have the line number This is really helpful because you have an exception on line 45. You just go to line 45 You don't look for the function. You go to the line. So this is really helpful and Hmm Almost there and we have the exception a stack trace contains as I said the exception if there is an exception We can have stack traces without exceptions. This is also nice if you want to trace something The function method call path to that exception it tells us where where we went to and what functions we called in order to get the error and We can use this to actually the book what's happening and this is easy because it's all the information is there alright the first thing that people Do when they're debugging case to read the exception and I showed you an exception that fits in a slide but you will believe me that real-world exceptions especially if you're using frameworks are like five scrolls long and if you have a big Exception it's hard to read it because you have to scroll and most of the code is not on your side It's not your code. It's on the framework side if you're developing Django and something's wrong with the model You're going to have at least two scrolls of Django DB models PY Calls where something's happening and you get a value error at the end and this is not really helpful So my first advice when reading an exception is to find the line that separates your cold from the framework called Because most of the times it's not a frameworks problem Sometimes there are books but most of the times it's your code that actually broke And if you're debugging can reading Django DB models stuck trace is not really helpful because each time It's the same thing and then you get an error and if you have a long stock trace It can be your cold framework your cold framework the line that separates it is usually If you start from the bottom and traverse up is the first piece of code that's on your side It's usually the call that triggered the exception So this is like a tip for reading long stock traces. Just find this line for example here In exceptions PY line 10 in parse daytime This is the line that separates after this I'm going to in Python library. I'm not interested there I don't know what's happening and probably this is not the bug because it's Python library that's been tested and in production and so on and so on so if you find the line You will find quickly the piece of code that actually broke This is the line it's in some list comprehension I'm doing stupid things just parsing the entire line as a daytime format, which is not actually right so There's a golden rule if there is a bug and you can write a test for the book You should write a test for that bug because otherwise you're going to fix this and something else is going to break And I call this constant regression and I've seen this in many projects And is and this can make you crazy. It's like fixing things and breaking color things It's fun if it's a game, but if it's a production code, it's not fun at all so if you find a book write a test for it and That's what we're doing here. It's for the slides if someone that wants to look after this It's a standard test. I'm writing a test and the test is failing So we're fixing the code. We're writing a parse line function. That's that does the naive approach of parsing by splitting and taking the parts so good and We're running the code again And as you can see we started with an exception that Some kind of a bracket cannot be parsed and now we see some kind of a daytime cannot be parsed And if you have a trained eye, you'll see the space in front of the daytime and this is the problem But if you have untrained eye You can start getting frustrated. So When this starts to happening, there is an exception. You fix the book You think you are fixing it you run another exception. It's the bugger time It's probably the most popular tool in Python I won't go into tails for PDB and IPDB because there are really good talks in on your Python for this, but I prefer using IPDB since it drops me in a nicer shell than PDB and The thing that we can do is set a breakpoint. I call this breakpoint I'm not sure if it's the correct term But you just put this on a shortcut in your editor put IPDB. Don't commit this on git. It breaks builds Once you run the code All right, forgot the slate So PDB interactive Python the bugger with console interface and stops the world and lets you look around This is the nice thing about it. You ask the values of the locally and globally defined names and you usually find the bug this way or you start jumping on Breakpoints or you start continuing the execution of the program and helps you look closely at what's happening And it's the better print function everybody starts with print and then moves to IPDB So when we run this program, we are dropped in an IPDB shell I'm sure all of you have seen this or is going to see this and use it And if I ask the second value, I'm going to see that here is a nasty little space So we have a bug. We should not forget to add a test for it. We're adding a test We're fixing the function by splitting by comma and a space because this is the format of our file and we're happy tests are passing now If tests are passing does this mean that we have a guarantee that Running the program is going to be okay Yes, no, how do you feel about it? No, no, yeah tests are good first step But we need to run real world and of course running the program boom another exception index out the French and as you can see the Exceptions themselves are not really helpful. It's value error value error index out the French and this is by far the Least helpful exception for me index out the French. What? There's something really wrong with this and I don't know why so More debugging time. I drop a pity IPDB in this parse line because I know this is the only place I use indexes iron the code and this is something that happens to Junior developers that start to understand and use IPDB you usually drop by the IPDB in the loop where there's 100,000 items that's going to be loop and you start hearing can't enter can't enter can't enter in After 10 minutes can't enter can't enter Because you need to you need to get to the line. That's actually breaking and this is also frustrating and time-wasting It's good to do it once or twice or when there's no other option and you're not sure what's happening, but IPDB there are some nice context manager called launch IPDB on exception which if we wrap the function and Run the code it's going to drop us in IPDB shell at the line that calls the exception Saves a lot of time. It's actually pretty nice and if I ask the value of parts, I'm going to see empty string and It's one element array. Do you know why this is? For someone that if you have parsed a lot of files, you know that files tend to have a new line at the end That if you split is going to result in a single item array with empty string So this is pretty nasty first time you hit it with a buggy a second time. You just know it and Add a code for it in the list comprehension with trip if it's empty. We don't want it and All good. Yep fix fix test passings all good programs running tests are passing. We're happy and as you saw The approach was we started them with an exception We fixed this exception which gave us another exception We fixed this exception with which gave us another exception And this is usually the step you're going to the steps you're going to follow when you're debugging It's either you see the problem in general and you fix it or you just fix this small problem in order to get to the second problem in order to get to the third problem problem and if you have tests You can know when you're ready. So this is kind of everyday debugging. You don't try to fix everything at once You just follow the step trace and the exceptions and in the end if you're lucky enough, you're going to have a working problem for at least some time and There are some exception types that are quite How to say useful and helpful? Like improperly configured validation error permission denied. This is when the frameworks The folks guys and girls that are developing the frameworks are nice and want to help you and in Django There is like tons of exceptions like improperly configured You messed up something they will raise you an exception and actually tell you what to do You are missing the metamodel Field here on this class or you cannot do this or you need to do this which is really helpful And that's why reading the stack traces is good Sometimes it can be helpful. Sometimes it can be it can be index out of range error Which at least in Python is good because if you're writing in C++ you you're going to get segmentation fault, which is even harder to the back All right, and fix it should be here fixes here are easy. Just read it fix it. Oh good and To summarize the first part Stack traces are your friend if you learn how to read them. You're going to the book faster They can be huge so looking for the line that separates your call from the framework call It's really helpful because it will save you a lot of scrolling and Often the problem is not in the framework Sometimes it is and if you learn how to use IPDB in my github repo for your Python 2017 I've added some Materials for shortcuts for IPDB if you learn how to use IPDB you're going to be really good at the bugging like since Stack Trace jumping around so on and if you hit a book write a test for it, I cannot emphasize more on this and The more I develop software the more I realize that tests are really important and you should write tests constant regression Yeah, I Don't want no one to suffer from constant regression All right. This was the first part. I have 30 more minutes. That's good second part We learn how to battle with exceptions, but now nothing's happening. You run your program There's no exception. There's no output. Nothing. Sorry nothing's happening and this starts to get frustrating because You're in the dark You don't know what if you have an exception you know what happened if nothing's happening You don't know what's happening That's the case and you need to find some source of flights. This is a detective work You need to quickly find a way to break things. I'll go there in a minute You need to know what should happen and what is the expected behavior because Oftentimes in students. I see They're struggling with something that's working And they don't know that it's working they expect something else to happen and this is really bad the bugging something That's actually working. So you should have a good idea what should happen and what is the expected behavior of the code and of course if you're in this case Daught everything because there are some pretty nasty gotchas that we're going to cover that can make your hair white and If there is no exception The quick fix for this is to look for error locks. Sometimes we just open a web browser. It says 500 This is it. Just a number Probably not the winning lottery number and there's no exception. No, you don't see an exception So you need to look for error locks in order to get an exception and this is actually For me, this is the more the most important thing when I'm debugging something that's not nothing's happening or something's odd I want to break it on purpose. I start typing random syntax errors I start raising as exceptions left and right in order to get an error to get the problem to fail so I can fix it and If I can break it, it's good. But if I cannot break it Then I need to isolate the code. That's not working For example, you're parsing some day times in a language. That's not raising cars. For example PHP Instead of parsing day times in your entire big project. Just take this piece of code Create a new file. This is like my most given advice to everyone create a new file and test the tested there Is it the same? Is it this code that you're debugging? That's actually wrong or is it something else? open a new file and do things there and Sprinkle with the boogers and trace every step of execution You need to know the value of everything. You need to know what's happening in order to see why nothing's happening This kind of sounded smart This should be on slides. So yeah code isolation is really your friend because if we're working on a 50 line Python script The bugging is pretty easy. You have 15 50 lines. You can read them But if you're working in a 50k Django project, sometimes you need to isolate the code Fix first the code and then go back to the framework and integrate the code in the framework It's more easy to work on something small than the Integral part of everything with Django and frameworks And there are some common gotchas that actually happen in Python and the first thing is module hiding I was debugging why you cannot import daytime from date from daytime for about an hour When I realized that the students named his file daytime.py We were reading the Python called reinstalling Python Opening issues What's happening like I open a repo on my computer and import it. I open a rep on his computer. I Cannot import it and in the frustration. I kind of changed directories. I managed to import daytime and it's alright We were very stupid this daytime dot py exception handling my favorite thing someone catches an exception and Passes and there's nothing no output. No stuck trace. Nothing's happening. It's really really bad If you're writing context managers, you can hide your exception really easy. I did this once There's a third argument. That's the exception. You need to check and Erase it It's okay. We're used to this kind of noise in Sofia alright, and other common gotchas is calling something by string and Making a typo and not having the code that's going to raise an exception if there's something wrong This is also really frustrating because there's nothing wrong. It's just the typo. It's just a string that you're calling a Classic thing you're debugging why this function is not working. Well in the first place we need to call this function it's like Writing a main method in a Python script and forgetting to add if name equals main called the called the main method really really classic classical thing and Editing the wrong file or running the wrong file. This is also debugging something that's working You're editing something at one place and running the same thing copy of it on another place There is no way for it to be working here breaking it on purpose works really well if you add random rubbish syntax error and the program still running you're most likely most likely here you're Editing your own file And of course debugging something that's working This is hard to catch because you need to know what means for your program to be working or not Sometimes you need just to know if this is okay and an example On Monday, I did a Django and salary training here on Europe. I turn I have an orange batch. It's really nice and I was some I was doing a live coding without preparation which always goals is planned and As you can see I have no registered tasks here in salary. It was working just a while ago. I Did something but I'm not asked and I don't know what happened Everything seems working when I start to panic and when I start to panic I do this thing called Binary search debugging which is dump and also really nice and it looks like this I Commented everything that I've added in user the user tasks. Puy. It's working. All right. So here's the problem I will get to the problem. I Uncommented the task and seller imports still working Uncommented the app imports that I met. I broke it commented a specific import working and Commented that import not working and I found the book and I don't know if this is an actual binary search But I like calling this binary search debugging because you're not putting your How to say your thoughts in the process. You're just commenting and checking. It's like good bisect pretty much doing what good bisect does and the generalized version of binary search debugging is Comment some parts of the code that you just added. So the program starts working and you're happy Uncomment a smaller portion of the code that you have just commented if if this is working then you can uncomment some more if It's not working then you go to step one but only for the code that you have just uncommented and things broke and by this you kind of Narrow down the Search area of in your in your project. So you know what's happening and you don't have to think about this You just need to comment and comment run comment and comment run until you have a small enough code to look at in order to find a problem and In the end you're going to find a breaking lines and I find this very very helpful because Sometimes you're tired frustrated. You don't want in something breaks that should not break You start doing this you find a problem quickly. You're happy. You go drink some beer at the beach or whatever you like to drink and a summary for nothing's happening Try to get an exception like this is the most important thing try to get an error so you can fix this error Isolate the code so you know that the thing you're working on is actually working and then try to integrate it in your project Because it's really bad to try to integrate something. That's not working in a project that actually can break the thing that you're integrating Yeah, make sure you know what needs to happen It's really important. Don't the book working things because you won't find a book Or if you find a book is going to be really strange and Try the binary search the bugging thing if The case is suitable for binary search the bugging where you just Comment and comment until you find a smaller portion of code where you can actually spot the bug or the typo All right, we know how to handle exceptions really nice. I love exceptions, you know the Famous thing that if you're cold runs from the first time it's really bad So try to get exceptions so you know that your cult is wrong Can you fixed it and now it's right if nothing's happening? There are several things that you can do but for me the worst thing of all is Everything's working There is no exception, but you get a wrong answer this is like the most frustrating thing because It's okay, but it's wrong. It's you and it's the algorithm that actually Needs debugging which is hard. This starts to get hard and you need to be focused and you need to be thinking a lot and When this happens, I usually for this five-step drip drip down I don't want this to sound click-baity or something like this, but it's just five steps that I Tend to do when I have a wrong answer and the five steps are like from Easy level to I should change my job level. So let's check them The first thing I always do is check tests because I usually test my thing with tests and If I get a wrong answer most likely my test is wrong and If you're doing Django, I don't know How many times it was the case that you need to refresh from DB your Model instance because you have a different state in your local test threat and this is like Fixing a lot of wrong answers first first check your tests write your tests good. Good tests are actually pretty hard to write I find this that you can write code actually pretty good with good abstraction writing good tests For me, it's even harder need to put more instruction more thinking And Not to make your tests need tests. Yeah, so check your tests If the test is correct Maybe you need validation. Maybe you've passed some wrong input Maybe you've passed something that your algorithm should not take in mind. So check this Is the value are the values that you're passing actually okay for you? Maybe you're passing wrong values then you need validation. This is good This is good because you add validation and your algorithm becomes more proof It's going to work more without breaking Now if you don't need validation and your tests are okay Then probably the next place you need to look at this at your algorithm, and I'm using an algorithm as a general Purpose called piece of code not by their search tree or something specific. That's called an algorithm I'm using this in the most general sense is your algorithm correct In order to catch correctness of algorithm You can either get a computer science degree and try to prove it formally Which is nice thing but takes a lot of time or you can put the buggers on each line of your algorithm and Put your headphones on or go somewhere else where you can focus and Start looking at values start looking at steps Is it from this step to this step? Do I have to do do I need those values or find the place where values get wrong? And this is quite hard to do and requires a lot of focus But for me, this is this is working really nice the burgers everywhere enter focus mode and start looking at values and most likely you will see where things get wrong Especially if there are for loops indexes or a sets whatever and this way you can fix your algorithm this is good but Things start to get worse if your algorithm is correct. Maybe your system design is not correct Maybe you designed this and forgot for a whole dimension of the problem It happens quite often it's like you do something for timelines in the future And suddenly you realize you need to do something for timelines in the past and you have zero code for this You don't have the models in place for this. You have nothing So here starting fresh and going to the white board is like the the way to go you need to Step away from the cold think again. Am I doing this right and maybe call it again or change the cold this is really really bad when it happens it happens from time to time and Probably the worst thing that can happen is if you don't understand the problem space well You have a wrong answer. For example, if I start doing data science If I get a wrong answer, I have no idea what to do There will be something about matrices and vectors and first I need to learn about matrices and vectors before I debug my matrices and vectors I need to learn about the problem space and This is bad when it happens because Someone else needs to fix your code or you need to do some quick and dirty hack And it's also good when it happens because it opens opportunities for new learning and this is always good and the Those were the five steps that you recap check tests check validation check algorithm trace every step Check system design. Are you actually solving the problem that you need to solve and finally Check your understanding of the entire problem space. Are you doing math and don't know math? for example and Finally some practical tips who I have ten more minutes so I can go through my last two slides five minutes each Alright some practical tips Explain your problem to someone. I'm sure you've heard of the term rubber duck debugging Sometimes there's no need to have a rubber duck. You have coworkers. You just you can use your coworkers as rubber ducks When someone asks me to help The first time I approach I always ask the question. What's happening? The the answer is usually it's not working and then I ask why it's not working and then the person starts Explaining to me why it's not working I'm not sure I listen carefully everything that he's explaining and suddenly the person is like, oh Yeah, yeah, wait a minute. I found my problem. Okay. I'll go down It sounds funny, but it actually helps a lot and if the person does not find the problem from his first explanation I ask again. Can you tell it again? And then I start listening so I can help But it really it really really really helps Explaining what you're doing to someone else Because then you're going to find if you have some small problem. You're going to find it If it's okay for you to talk to a rubber duck talk to rubber duck Whatever you find suitable Something I really like If you're frustrated and you have deadlines and you have a problem and you're you're not in your best Mood and shape to fix the book now, but it needs to be fixed You can practice the so-called power parallel debugging Which is ask a question of that car for all open a github issue ask a co-worker and continue working on the book it's like Give more more inputs to your to your problem because sometimes You're struggling with something and someone on stock or fall actually Answers the question and says you're doing this entirely wrong. Take a look at this and then you're and then you're ready or Sometimes someone on a github issue says I have the same problem Here is my coat and system and whatever you look at it and you find the problem that you're also having When a co-worker is thinking about it Also good more heads in the problem. So this can This is not actually nice because you're like firing random questions on stock or fall and github issues and I know people who are supporting open source They don't like this very much because it's like fix my problem at my work because I'm using your open source open source library so it's important when you do parallel debugging to Push back not push back but Contribute back to the community Answer questions on stock overfall if you see someone asking a question that you've been struggling with for a week Just sit down for 30 minutes and answer him. So other people can see it as Make poor request for documentation. I love doing this when I struggle with something That's not really nice nicely described in a tutorial documentation. I do it and Contribute back to the documentation. So other people won't waste time because I'm not wasting time when there is a good documentation and people before me have done this and Yeah answer to issues Help help other people because this is the way it can get better for everyone and waste Smaller amount of amount of time see bug fixes and One specific tip for stock overfall Read the small comments next to the answers because sometimes they Contain the better answer to the answer. They're like really eight pixel phones comments but they're also really good and Do a talk on a conference? It's nice to share experience seem to be helpful to other people and I guess this is it for me Thanks everyone if you have questions, we have like ten minutes. Yes, we have nine minutes twenty seconds for questions. All right Hi Great. Thank you very much. I just wanted to add to this parallel programming one crucial step Why we don't like it in open source and why how you can make it make us love you for doing this When you solve the bug go back to all those places where you asked about it Yes, and write the solution there and close your issue. Yes. Yes This does changes everything and we will absolutely love you for that. I Agree so if you go to a github and you solve your problem close your issue Write how you solve your issue make a pre-quest. Don't just leave it hanging there. It's it's I know it's bad Great talk. Thank you. I would like to know for example If you have a test that so many times works and it's so many times doesn't work What is your strategy of the best strategy to fix this? Yes, so that's actually a good question What do we do when we have this test that's working half the times not working together half the time so We had such a test a month ago The thing that we did is run the test a hundred times is like Write a bus script run the test go to go grab a lunch Go back collect the locks see where it's failing can start the bugging it. It was for us. It was a faker generating Names that were not compliant with our capitalized function and tests were failing can't run them and it's For me, it's like run it a lot See where it breaks run a lot the point that breaks and check values check what's happening Why why with this specific value? It's it's failing If you have tests that are failing the test may be failing because you have a different How to say system operating system when you're running come For example Jenkins. There were some really nice talk yesterday about docker rising py test like having the same Operating system on your machine in docker and the same thing running on Jenkins So you need to do this is like the nothing's happening. You need to do the detective work find what's happening can't fix it It's a nasty thing to happen Any other question? Have you considered using more visualized visualize the buggers like WDB or built-in ID the buggers like Python the bugger I Think this is like a personal taste For me is whatever works for you if you like more visual debugging. There are a lot of tools for this I'm a person who lives in the console. So I debug in the console It's a personal taste. Whatever works for you should be the tools that you're using and I can't I am coming from Java World where visual debuggers starting like next next next whole day the bugging I Something not related to debugging, but I was curious you mentioned something about the code Academy. Yeah in the Sofia Yeah Can you give us? I don't know a little idea of how long the courses and how long does it usually take people? All right So so the thing that we're doing in Sofia is called it's called hack Bulgaria and now it's being rebranded to hack software Academy for whatever reasons We do courses that are named programming one-on-one with Python, which is a four month long course we require some Programming skills before you enter and for like four months. We do Quite a lot of stuff. It's like three times a week for hours coding on place It's not like just lectures and it's working. It's intensive. It's working because it's intensive it and it's the way to learn for us Well, thank you everyone