|
| https://realpython.com/ |
| Start Here | https://realpython.com/start-here/ |
|
Learn Python
| https://realpython.com/lessons/debugging/ |
| Python Tutorials →In-depth articles and video courses | https://realpython.com/search?kind=article&kind=course&order=newest |
| Learning Paths →Guided study plans for accelerated learning | https://realpython.com/learning-paths/ |
| Quizzes & Exercises →Check your learning progress | https://realpython.com/quizzes/ |
| Browse Topics →Focus on a specific area or skill level | https://realpython.com/tutorials/all/ |
| Community Chat →Learn with other Pythonistas | https://realpython.com/community/ |
| Office Hours →Live Q&A calls with Python experts | https://realpython.com/office-hours/ |
| Podcast →Hear what’s new in the world of Python | https://realpython.com/podcasts/rpp/ |
| Books →Round out your knowledge and learn offline | https://realpython.com/products/books/ |
| Reference →Concise definitions for common Python terms | https://realpython.com/ref/ |
| Code Mentor →BetaPersonalized code assistance & learning tools | https://realpython.com/mentor/ |
| Unlock All Content → | https://realpython.com/account/join/ |
|
More
| https://realpython.com/lessons/debugging/ |
| Learner Stories | https://realpython.com/learner-stories/ |
| Python Newsletter | https://realpython.com/newsletter/ |
| Python Job Board | https://www.pythonjobshq.com |
| Meet the Team | https://realpython.com/team/ |
| Become a Tutorial Writer | https://realpython.com/write-for-us/ |
| Become a Video Instructor | https://realpython.com/become-an-instructor/ |
| Search | https://realpython.com/search |
| https://realpython.com/search |
| Join | https://realpython.com/account/join/ |
| Sign‑In | https://realpython.com/account/login/?next=%2Flessons%2Fdebugging%2F |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson&utm_content=python-print |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson&utm_content=python-print |
| https://realpython.com/courses/python-print/#team |
| The Python print() Function: Go Beyond the Basics | https://realpython.com/courses/python-print/ |
| Christopher Trudeau | https://realpython.com/courses/python-print/#team |
| Recommended Tutorial | https://realpython.com/python-print/ |
| Course Slides (.pdf) | https://realpython.com/courses/python-print/downloads/slides-print/ |
| Sample Code (.zip) | https://realpython.com/courses/python-print/downloads/code-print/ |
| Ask a Question | https://realpython.com/lessons/debugging/#discussion |
| https://realpython.com/feedback/survey/course/python-print/liked/?from=lesson-title |
| https://realpython.com/feedback/survey/course/python-print/disliked/?from=lesson-title |
| Contents | https://realpython.com/lessons/debugging/#description |
| Transcript | https://realpython.com/lessons/debugging/#transcript |
| Discussion (4) | https://realpython.com/lessons/debugging/#discussion |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson_preview&utm_content=python-print |
| Sign-In | https://realpython.com/account/login/ |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson_preview&utm_content=python-print |
| Sign-In | https://realpython.com/account/login/ |
| 00:00 | https://realpython.com/lessons/debugging/#t=0.51 |
| In the previous lesson, I showed you how to use the mock library to write better | https://realpython.com/lessons/debugging/#t=0.51 |
| tests, | https://realpython.com/lessons/debugging/#t=3.81 |
| particularly when you’re testing code that has side effects like print(). In this | https://realpython.com/lessons/debugging/#t=4.5 |
| lesson, I’m going to dive a little deeper into debugging. | https://realpython.com/lessons/debugging/#t=8.97 |
| 00:12 | https://realpython.com/lessons/debugging/#t=12.96 |
| I often find the hardest part of programming is actually finding and squashing | https://realpython.com/lessons/debugging/#t=12.96 |
| the bugs. print() is a quick and easy way to help you hunt these things down to tell | https://realpython.com/lessons/debugging/#t=16.17 |
| you what’s going on inside of your code. | https://realpython.com/lessons/debugging/#t=20.46 |
| 00:23 | https://realpython.com/lessons/debugging/#t=23.07 |
| It’s jokingly sometimes referred to as caveman debugging because it’s a simple | https://realpython.com/lessons/debugging/#t=23.07 |
| and sort of old fashioned way of doing things, | https://realpython.com/lessons/debugging/#t=27.12 |
| but often it is quite useful. In order to show you how to use print() to help you | https://realpython.com/lessons/debugging/#t=29.7 |
| debug, I need to have some code to debug. The method on the screen at the moment | https://realpython.com/lessons/debugging/#t=34.47 |
| generates a Roman numeral | https://realpython.com/lessons/debugging/#t=38.88 |
| and it makes an assumption that it’s a four-digit Roman numeral, because it’s for | https://realpython.com/lessons/debugging/#t=40.59 |
| creating the copyright year in Roman numerals | https://realpython.com/lessons/debugging/#t=43.98 |
| that would be at the end of movie credits. The code works as follows. | https://realpython.com/lessons/debugging/#t=47.01 |
| 00:52 | https://realpython.com/lessons/debugging/#t=52.05 |
| There’s a dictionary at the top that declares the common letters that are used | https://realpython.com/lessons/debugging/#t=52.05 |
| in Roman numerals. Start with a divisor of 1000, essentially | https://realpython.com/lessons/debugging/#t=55.5 |
| assuming that our number is going to be a four-digit year. And then it loops | https://realpython.com/lessons/debugging/#t=59.67 |
| through those divisors, essentially peeling off each of the digits, | https://realpython.com/lessons/debugging/#t=63.72 |
| one at a time. For each digit, it looks up in the hash | https://realpython.com/lessons/debugging/#t=67.08 |
| the value of the Roman numeral corresponding to the digit, | https://realpython.com/lessons/debugging/#t=71.43 |
| and then prints out multiple versions of it if necessary. So for example, | https://realpython.com/lessons/debugging/#t=75.33 |
| if the digit is less than 3, it takes the divisor, | https://realpython.com/lessons/debugging/#t=79.47 |
| which is—if the first time, it will be 1000— | https://realpython.com/lessons/debugging/#t=83.25 |
| the thousands position, and prints out digit number of them. | https://realpython.com/lessons/debugging/#t=86.01 |
| 01:31 | https://realpython.com/lessons/debugging/#t=91.35 |
| If you put in the year 2000, | https://realpython.com/lessons/debugging/#t=91.35 |
| you will get 2 * roman[divisor], look up 1000, | https://realpython.com/lessons/debugging/#t=93.33 |
| which gives you your two 'M'’s for your 2000. Similar logic is used | https://realpython.com/lessons/debugging/#t=97.98 |
| if the digit is a 4, if the digit is between 5 and 8, | https://realpython.com/lessons/debugging/#t=101.94 |
| and if the digit is equal to 9. Seeing as I’m going to show you how to debug, | https://realpython.com/lessons/debugging/#t=105.66 |
| there’s some bugs in this code. | https://realpython.com/lessons/debugging/#t=109.71 |
| 01:52 | https://realpython.com/lessons/debugging/#t=112.47 |
| I’m going to try it out and see if I can find them. | https://realpython.com/lessons/debugging/#t=112.47 |
| Start off with a movie year of 2000, get back 'MM'. So far, so good. | https://realpython.com/lessons/debugging/#t=115.05 |
| That’s right. Now, I’m going to try 2015. | https://realpython.com/lessons/debugging/#t=119.7 |
| 02:04 | https://realpython.com/lessons/debugging/#t=124.41 |
| Well, that’s a problem. MMX is 2010. | https://realpython.com/lessons/debugging/#t=124.41 |
| There’s obviously an issue with the code. | https://realpython.com/lessons/debugging/#t=128.28 |
| Now what you want to do is put a bunch of print() statements in the code to see | https://realpython.com/lessons/debugging/#t=130.8 |
| what happens at each step. I’ve created a bunch. | https://realpython.com/lessons/debugging/#t=134.76 |
| 02:20 | https://realpython.com/lessons/debugging/#t=140.04 |
| The first one here at line 6 will tell me that the movie_year() has been called | https://realpython.com/lessons/debugging/#t=140.04 |
| and what number is being debugged, to make sure things are happening properly. At | https://realpython.com/lessons/debugging/#t=144.66 |
| line 8, | https://realpython.com/lessons/debugging/#t=149.52 |
| I’m printing out what digit is currently being processed and what the divisor | https://realpython.com/lessons/debugging/#t=150.06 |
| is. You’ll notice that I put a few spaces in here. I like to do this | https://realpython.com/lessons/debugging/#t=153.57 |
| when I’m putting print() statements in for debug. | https://realpython.com/lessons/debugging/#t=157.89 |
| 02:40 | https://realpython.com/lessons/debugging/#t=160.38 |
| What will happen is line 6 will put things flush against the left-hand side, | https://realpython.com/lessons/debugging/#t=160.38 |
| and all subsequent calls will be indented. | https://realpython.com/lessons/debugging/#t=165.36 |
| It’s easy for me to see on the screen when another function is called | https://realpython.com/lessons/debugging/#t=168.42 |
| because it’ll be back out at the outset. Down at the bottom, | https://realpython.com/lessons/debugging/#t=171.87 |
| I’m printing out the state of output on each iteration of the loop. | https://realpython.com/lessons/debugging/#t=176.07 |
| 03:02 | https://realpython.com/lessons/debugging/#t=182.32 |
| Great. So I’ve got the print() statements in there. | https://realpython.com/lessons/debugging/#t=182.32 |
| I’m going to call the troubled 2015 again. | https://realpython.com/lessons/debugging/#t=185.8 |
| 03:12 | https://realpython.com/lessons/debugging/#t=192.34 |
| The first print() statement shows me that 2015 was called. The first iteration | https://realpython.com/lessons/debugging/#t=192.34 |
| shows digit=2 divison=1000, | https://realpython.com/lessons/debugging/#t=197.56 |
| which spits out the 'MM'—so far, so good. | https://realpython.com/lessons/debugging/#t=199.99 |
| 03:23 | https://realpython.com/lessons/debugging/#t=203.5 |
| The next digit is a 0. Well, right off you’ll notice | https://realpython.com/lessons/debugging/#t=203.5 |
| there is no if statement handling this. | https://realpython.com/lessons/debugging/#t=207.7 |
| Now, it works out because 0 is less than 3 and 0 times the hundreds | https://realpython.com/lessons/debugging/#t=210.31 |
| digit will put out zero characters— | https://realpython.com/lessons/debugging/#t=216.22 |
| so technically, line 11 is getting called, but it’s getting called with a blank. | https://realpython.com/lessons/debugging/#t=219.28 |
| 03:43 | https://realpython.com/lessons/debugging/#t=223.93 |
| It’s not really a bug, but it’s not particularly efficient. | https://realpython.com/lessons/debugging/#t=223.93 |
| 03:48 | https://realpython.com/lessons/debugging/#t=228.19 |
| Next, on to the third digit. The divisor is now 10. | https://realpython.com/lessons/debugging/#t=228.19 |
| This happens correctly. On to the last digit, digit=5. | https://realpython.com/lessons/debugging/#t=232.84 |
| 03:57 | https://realpython.com/lessons/debugging/#t=237.25 |
| The divisor is 1, | https://realpython.com/lessons/debugging/#t=237.25 |
| and nothing’s getting called. A quick inspection of the code shows that line 14 | https://realpython.com/lessons/debugging/#t=238.54 |
| has an elif of < 5. The case for 5 | https://realpython.com/lessons/debugging/#t=244.78 |
| actually isn’t in the code at the moment. | https://realpython.com/lessons/debugging/#t=248.98 |
| 04:14 | https://realpython.com/lessons/debugging/#t=254.41 |
| So, I’ll make a couple changes. First, line 9. | https://realpython.com/lessons/debugging/#t=254.41 |
| This makes the code a little more efficient. And line 14, | https://realpython.com/lessons/debugging/#t=258.79 |
| I fixed the less than or equal to (<=). | https://realpython.com/lessons/debugging/#t=262.21 |
| 04:26 | https://realpython.com/lessons/debugging/#t=266.98 |
| Now—as expected—when I rerun it, | https://realpython.com/lessons/debugging/#t=266.98 |
| 04:32 | https://realpython.com/lessons/debugging/#t=272.02 |
| processing looks much better this time, with the correct result. | https://realpython.com/lessons/debugging/#t=272.02 |
| 04:37 | https://realpython.com/lessons/debugging/#t=277.3 |
| Using print() as a quick tool to insert in your code and see what’s going on is | https://realpython.com/lessons/debugging/#t=277.3 |
| useful for debugging. It does have some problems though. First off, | https://realpython.com/lessons/debugging/#t=281.77 |
| not all software runs in a terminal. | https://realpython.com/lessons/debugging/#t=286.72 |
| 04:49 | https://realpython.com/lessons/debugging/#t=289.06 |
| Adding print() statements to server side code | https://realpython.com/lessons/debugging/#t=289.06 |
| isn’t going to be particularly helpful if | https://realpython.com/lessons/debugging/#t=291.13 |
| there’s no terminal for you to see what’s going on. Secondly, | https://realpython.com/lessons/debugging/#t=292.81 |
| you may have to look for clues to a bug long after the bug has happened. For long | https://realpython.com/lessons/debugging/#t=296.62 |
| running services, you need to get at information | https://realpython.com/lessons/debugging/#t=301.3 |
| when a customer complains about something that went wrong yesterday, | https://realpython.com/lessons/debugging/#t=304.0 |
| the day before, possibly even months earlier. | https://realpython.com/lessons/debugging/#t=307.0 |
| 05:10 | https://realpython.com/lessons/debugging/#t=310.45 |
| Last, print() isn’t thread-safe. Now for simple programs, this isn’t a problem, | https://realpython.com/lessons/debugging/#t=310.45 |
| but if you are doing multithreaded processing, print() will mess things up. | https://realpython.com/lessons/debugging/#t=315.25 |
| 05:19 | https://realpython.com/lessons/debugging/#t=319.09 |
| You can end up with print() statements overlapping each other, | https://realpython.com/lessons/debugging/#t=319.09 |
| and that can cause all sorts of weirdnesses inside of your terminal. | https://realpython.com/lessons/debugging/#t=321.73 |
| As an alternative, | https://realpython.com/lessons/debugging/#t=325.54 |
| you can use the logging libraries built into Python. Python has a very powerful, | https://realpython.com/lessons/debugging/#t=326.35 |
| very configurable logging mechanism. | https://realpython.com/lessons/debugging/#t=330.85 |
| 05:32 | https://realpython.com/lessons/debugging/#t=332.92 |
| It’s a little harder to get going than a simple print() statement, | https://realpython.com/lessons/debugging/#t=332.92 |
| but it is much more safe for large applications. | https://realpython.com/lessons/debugging/#t=335.74 |
| Typically, your logging system sends output to a file. In large enterprises, | https://realpython.com/lessons/debugging/#t=339.61 |
| there are often tools for sending them off to a common location, searching them, | https://realpython.com/lessons/debugging/#t=343.72 |
| rotating them, filtering them— | https://realpython.com/lessons/debugging/#t=347.59 |
| there’s lots and lots of tools that can help your debugging through manipulating | https://realpython.com/lessons/debugging/#t=349.81 |
| your logs. | https://realpython.com/lessons/debugging/#t=353.38 |
| 05:55 | https://realpython.com/lessons/debugging/#t=355.09 |
| So, here’s a simple function that counts the number of lowercase letters inside | https://realpython.com/lessons/debugging/#t=355.09 |
| of a string. | https://realpython.com/lessons/debugging/#t=358.76 |
| I’m going to use this to show off the features of logging. In order to use the | https://realpython.com/lessons/debugging/#t=359.9 |
| logger, | https://realpython.com/lessons/debugging/#t=363.53 |
| first thing—you need to import logging from the package system. Built into | https://realpython.com/lessons/debugging/#t=364.22 |
| logging is something called basicConfig(). | https://realpython.com/lessons/debugging/#t=369.08 |
| 06:11 | https://realpython.com/lessons/debugging/#t=371.24 |
| This is the easiest way to configure a logger. | https://realpython.com/lessons/debugging/#t=371.24 |
| The configuration I’m passing at the moment | https://realpython.com/lessons/debugging/#t=373.73 |
| specifies the stream to be stdout (standard out). | https://realpython.com/lessons/debugging/#t=375.62 |
| 06:18 | https://realpython.com/lessons/debugging/#t=378.2 |
| This means the content will be printed to the screen. | https://realpython.com/lessons/debugging/#t=378.2 |
| 06:22 | https://realpython.com/lessons/debugging/#t=382.31 |
| In this configuration, logger calls are very, | https://realpython.com/lessons/debugging/#t=382.31 |
| very similar to just print() statements. | https://realpython.com/lessons/debugging/#t=384.98 |
| The second parameter I’m passing in is the level. | https://realpython.com/lessons/debugging/#t=387.98 |
| 06:30 | https://realpython.com/lessons/debugging/#t=390.83 |
| The logger has four different levels: INFO, DEBUG, WARNING, and ERROR. | https://realpython.com/lessons/debugging/#t=390.83 |
| By setting this value, you’re turning on a filter. | https://realpython.com/lessons/debugging/#t=396.29 |
| 06:39 | https://realpython.com/lessons/debugging/#t=399.92 |
| This is the most promiscuous filter—it says all calls can be caught. | https://realpython.com/lessons/debugging/#t=399.92 |
| 06:45 | https://realpython.com/lessons/debugging/#t=405.11 |
| Finally, I’ve got logging configured, | https://realpython.com/lessons/debugging/#t=405.11 |
| so I need to actually instantiate a logger. | https://realpython.com/lessons/debugging/#t=407.15 |
| I do that through the getLogger() mechanism. | https://realpython.com/lessons/debugging/#t=409.52 |
| 06:52 | https://realpython.com/lessons/debugging/#t=412.22 |
| By passing in __name__, | https://realpython.com/lessons/debugging/#t=412.22 |
| I’m creating a logger with the same name as this file. That allows me inside of the | https://realpython.com/lessons/debugging/#t=414.35 |
| logs to easily distinguish between where a particular logging statement came | https://realpython.com/lessons/debugging/#t=419.03 |
| from. | https://realpython.com/lessons/debugging/#t=423.11 |
| 07:05 | https://realpython.com/lessons/debugging/#t=425.69 |
| Line 8 is an .info() call to the logger. | https://realpython.com/lessons/debugging/#t=425.69 |
| This is similar to the print() statement I used at the beginning of the movie_year() | https://realpython.com/lessons/debugging/#t=428.81 |
| function, telling me that I’m inside of this function call. Inside of the | https://realpython.com/lessons/debugging/#t=431.78 |
| loop that checks the case on the letters, I put in a .debug() statement, | https://realpython.com/lessons/debugging/#t=437.69 |
| and you’ll notice that the message here uses the %s C-style mechanism for | https://realpython.com/lessons/debugging/#t=441.98 |
| injecting content inside of a string. | https://realpython.com/lessons/debugging/#t=447.35 |
| 07:30 | https://realpython.com/lessons/debugging/#t=450.62 |
| I’ll come back to why you use that in a minute. Finally, | https://realpython.com/lessons/debugging/#t=450.62 |
| I also send another .info() setting so that I can see what’s being returned by the | https://realpython.com/lessons/debugging/#t=454.91 |
| method. Easy enough. Let’s see this in action. | https://realpython.com/lessons/debugging/#t=460.46 |
| 07:46 | https://realpython.com/lessons/debugging/#t=466.01 |
| Importing the method, calling the method. | https://realpython.com/lessons/debugging/#t=466.01 |
| 07:52 | https://realpython.com/lessons/debugging/#t=472.94 |
| It gets called. | https://realpython.com/lessons/debugging/#t=472.94 |
| The first four statements on the screen are from the system stdout— | https://realpython.com/lessons/debugging/#t=474.41 |
| that’s the logger calling logger.info(), | https://realpython.com/lessons/debugging/#t=479.03 |
| logger.debug() twice inside of the loop, and logger.info() again at the end. | https://realpython.com/lessons/debugging/#t=481.37 |
| 08:07 | https://realpython.com/lessons/debugging/#t=487.55 |
| The 2 is the actual return value of this function. | https://realpython.com/lessons/debugging/#t=487.55 |
| 08:12 | https://realpython.com/lessons/debugging/#t=492.59 |
| I commented earlier that these things can be filtered. | https://realpython.com/lessons/debugging/#t=492.59 |
| If you look at line 4, I’ve changed the logging level to INFO. | https://realpython.com/lessons/debugging/#t=496.49 |
| If I rerun the call | https://realpython.com/lessons/debugging/#t=500.48 |
| now, only those .debug() methods with the INFO setting are getting printed out. | https://realpython.com/lessons/debugging/#t=501.77 |
| 08:28 | https://realpython.com/lessons/debugging/#t=508.55 |
| This allows you to set different levels of what’s being captured in your logs. | https://realpython.com/lessons/debugging/#t=508.55 |
| 08:33 | https://realpython.com/lessons/debugging/#t=513.89 |
| This brings me back to the %s mechanism. | https://realpython.com/lessons/debugging/#t=513.89 |
| Although generally it’s recommended to use f-strings when formatting, debug logs | https://realpython.com/lessons/debugging/#t=517.22 |
| are the exception. You’ll notice in line 12 | https://realpython.com/lessons/debugging/#t=521.929 |
| that I’m passing in the string for formatting | https://realpython.com/lessons/debugging/#t=525.65 |
| and then the attributes into the logging call itself, rather than the usual | https://realpython.com/lessons/debugging/#t=527.69 |
| mechanism of putting the string, %, and then the parameters. | https://realpython.com/lessons/debugging/#t=532.07 |
| 08:56 | https://realpython.com/lessons/debugging/#t=536.85 |
| The creation of the string actually happens inside of the function. | https://realpython.com/lessons/debugging/#t=536.85 |
| You can’t do this with a formatted string. | https://realpython.com/lessons/debugging/#t=541.5 |
| The reason this is important is if the filters are turned on, | https://realpython.com/lessons/debugging/#t=544.2 |
| the string doesn’t get created, as string operations can be expensive. | https://realpython.com/lessons/debugging/#t=547.62 |
| 09:12 | https://realpython.com/lessons/debugging/#t=552.03 |
| That means when the debugger is set to INFO, this .debug() call | https://realpython.com/lessons/debugging/#t=552.03 |
| doesn’t actually create the string by passing the letter object into this string | https://realpython.com/lessons/debugging/#t=556.29 |
| and creating it. This skips a whole bunch of processing. | https://realpython.com/lessons/debugging/#t=560.85 |
| 09:24 | https://realpython.com/lessons/debugging/#t=564.66 |
| If I had used an f-string here, | https://realpython.com/lessons/debugging/#t=564.66 |
| it would have created the fully impregnated string to pass it as an argument | https://realpython.com/lessons/debugging/#t=566.31 |
| into the debugger. | https://realpython.com/lessons/debugging/#t=570.15 |
| You can significantly reduce the amount of processing necessary on your .debug() | https://realpython.com/lessons/debugging/#t=571.71 |
| calls by using the old style C formatting. Python’s logging module is very | https://realpython.com/lessons/debugging/#t=575.13 |
| powerful, and it does this through being very configurable. | https://realpython.com/lessons/debugging/#t=580.95 |
| 09:43 | https://realpython.com/lessons/debugging/#t=583.95 |
| The basicConfig() mechanism that I showed you is the easiest way to get up and | https://realpython.com/lessons/debugging/#t=583.95 |
| going, | https://realpython.com/lessons/debugging/#t=587.43 |
| but you can fine-tune how your logging experience works. To give you a small | https://realpython.com/lessons/debugging/#t=588.03 |
| taste of that, | https://realpython.com/lessons/debugging/#t=592.59 |
| here’s an example piece of code that combines the ANSI escape sequences used in | https://realpython.com/lessons/debugging/#t=593.97 |
| earlier lessons with the configuration of a logger. | https://realpython.com/lessons/debugging/#t=599.07 |
| 10:02 | https://realpython.com/lessons/debugging/#t=602.82 |
| This format string uses the ANSI escape to bold the function name inside of the | https://realpython.com/lessons/debugging/#t=602.82 |
| message to make it easier to read on a terminal. In order to use this, | https://realpython.com/lessons/debugging/#t=608.04 |
| you need to set the logging level, add a StreamHandler, and then add a Formatter, | https://realpython.com/lessons/debugging/#t=612.33 |
| and all of that gets passed into the root.addHandler(). | https://realpython.com/lessons/debugging/#t=617.73 |
| 10:21 | https://realpython.com/lessons/debugging/#t=621.06 |
| The basicConfig() call that you saw earlier does a version of these four steps | https://realpython.com/lessons/debugging/#t=621.06 |
| for you. | https://realpython.com/lessons/debugging/#t=624.93 |
| You’ve made it so far—only one lesson left. In this last lesson, | https://realpython.com/lessons/debugging/#t=626.76 |
| I’ll talk about where you can get more information on some of the topics I’ve | https://realpython.com/lessons/debugging/#t=630.45 |
| talked about, and useful libraries you can take advantage of that can help you do | https://realpython.com/lessons/debugging/#t=633.24 |
| some of the things I’ve shown you. | https://realpython.com/lessons/debugging/#t=636.39 |
| June 10, 2020 | https://realpython.com/lessons/debugging/#comment-a115f5c9-42f0-4248-a7ed-108e4408aa59 |
| July 7, 2020 | https://realpython.com/lessons/debugging/#comment-59007129-83fc-4edf-a474-9f2389e6473e |
| Jan. 17, 2021 | https://realpython.com/lessons/debugging/#comment-30ce4fcc-87b1-4a46-b530-57fadd7f28a2 |
| Jan. 19, 2021 | https://realpython.com/lessons/debugging/#comment-b977a88e-704e-4827-837c-f828982a1de0 |
| Become a Member | https://realpython.com/account/join/ |
| https://realpython.com/lessons/mocking-print-unit-tests/ |
| Overview | https://realpython.com/courses/python-print/ |
| https://realpython.com/lessons/the-python-print-function-quiz/ |
|
Basic Usage and String Literals 08:25
| https://realpython.com/videos/basic-usage-and-string-literals/ |
|
String Formatting Styles 03:42
| https://realpython.com/videos/formatting/ |
|
sep, end, and flush 07:23
| https://realpython.com/videos/sep-end-and-flush/ |
|
Printing to File Streams 02:43
| https://realpython.com/lessons/printing-file-streams/ |
|
Custom Data Types 04:56
| https://realpython.com/lessons/custom-data-types/ |
|
Python 2's print vs Python 3's print() 01:50
| https://realpython.com/lessons/python-2s-print-vs-python-3s-print/ |
|
Pretty Print 03:27
| https://realpython.com/lessons/pretty-print/ |
|
ANSI Escape Sequences 01:57
| https://realpython.com/lessons/ansi-escape-sequences/ |
|
Animation 04:12
| https://realpython.com/lessons/animation/ |
|
Mocking print() in Unit Tests 05:42
| https://realpython.com/lessons/mocking-print-unit-tests/ |
|
Debugging 10:40
| https://realpython.com/lessons/debugging/ |
|
The Python print() Function (Quiz) 12:00
| https://realpython.com/lessons/the-python-print-function-quiz/ |
|
Related Information 02:05
| https://realpython.com/lessons/related-information/ |
| Privacy Policy | https://realpython.com/privacy-policy/ |
Viewport: width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover