René's URL Explorer Experiment


Title: Debugging (Video) – Real Python

Open Graph Title: Debugging – Real Python

Description: In the previous lesson, I showed you how to use the mock library to write better tests, particularly when you’re testing code that has side effects like print(). In this lesson, I’m going to dive a little deeper into debugging. I often find the…

Open Graph Description: In the previous lesson, I showed you how to use the mock library to write better tests, particularly when you’re testing code that has side effects like print(). In this lesson, I’m going to dive a little deeper into debugging. I often find the…

Opengraph URL: https://realpython.com/lessons/debugging/

X: @realpython

direct link

Domain: realpython.com


Hey, it has json ld scripts:
  {
    "@context": "https://schema.org",
    "@type": "VideoObject",
    "name": "Debugging",
    "description": "In the previous lesson, I showed you how to use the mock library to write better tests, particularly when you’re testing code that has side effects like print(). In this lesson, I’m going to dive a little deeper into debugging. I often find the…",
    "thumbnailUrl": ["https://files.realpython.com/media/The-Python-Print-Function_Watermarked.26066d64ad82.jpg"],
    "uploadDate": "2020-05-05T14:00:00+00:00",
    "duration": "PT10M40S",
    
    "potentialAction": {
      "@type": "SeekToAction",
      "target": "https://realpython.com/lessons/debugging/#t={seek_to_second_number}",
      "startOffset-input": "required name=seek_to_second_number"
    }
  }
  

authorReal Python
twitter:cardsummary_large_image
twitter:imagehttps://files.realpython.com/media/The-Python-Print-Function_Watermarked.26066d64ad82.jpg
og:imagehttps://files.realpython.com/media/The-Python-Print-Function_Watermarked.26066d64ad82.jpg
twitter:creator@realpython
og:typevideo.episode

Links:

https://realpython.com/
Start Herehttps://realpython.com/start-here/
Learn Python https://realpython.com/lessons/debugging/
Python Tutorials →In-depth articles and video courseshttps://realpython.com/search?kind=article&kind=course&order=newest
Learning Paths →Guided study plans for accelerated learninghttps://realpython.com/learning-paths/
Quizzes & Exercises →Check your learning progresshttps://realpython.com/quizzes/
Browse Topics →Focus on a specific area or skill levelhttps://realpython.com/tutorials/all/
Community Chat →Learn with other Pythonistashttps://realpython.com/community/
Office Hours →Live Q&A calls with Python expertshttps://realpython.com/office-hours/
Podcast →Hear what’s new in the world of Pythonhttps://realpython.com/podcasts/rpp/
Books →Round out your knowledge and learn offlinehttps://realpython.com/products/books/
Reference →Concise definitions for common Python termshttps://realpython.com/ref/
Code Mentor →BetaPersonalized code assistance & learning toolshttps://realpython.com/mentor/
Unlock All Content →https://realpython.com/account/join/
More https://realpython.com/lessons/debugging/
Learner Storieshttps://realpython.com/learner-stories/
Python Newsletterhttps://realpython.com/newsletter/
Python Job Boardhttps://www.pythonjobshq.com
Meet the Teamhttps://realpython.com/team/
Become a Tutorial Writerhttps://realpython.com/write-for-us/
Become a Video Instructorhttps://realpython.com/become-an-instructor/
Searchhttps://realpython.com/search
https://realpython.com/search
Joinhttps://realpython.com/account/join/
Sign‑Inhttps://realpython.com/account/login/?next=%2Flessons%2Fdebugging%2F
Unlock This Lessonhttps://realpython.com/account/join/?utm_source=rp_lesson&utm_content=python-print
Unlock This Lessonhttps://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 Basicshttps://realpython.com/courses/python-print/
Christopher Trudeauhttps://realpython.com/courses/python-print/#team
Recommended Tutorialhttps://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 Questionhttps://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
Contentshttps://realpython.com/lessons/debugging/#description
Transcripthttps://realpython.com/lessons/debugging/#transcript
Discussion (4)https://realpython.com/lessons/debugging/#discussion
Unlock This Lessonhttps://realpython.com/account/join/?utm_source=rp_lesson_preview&utm_content=python-print
Sign-Inhttps://realpython.com/account/login/
Unlock This Lessonhttps://realpython.com/account/join/?utm_source=rp_lesson_preview&utm_content=python-print
Sign-Inhttps://realpython.com/account/login/
00:00https://realpython.com/lessons/debugging/#t=0.51
In the previous lesson, I showed you how to use the mock library to write betterhttps://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 thishttps://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:12https://realpython.com/lessons/debugging/#t=12.96
I often find the hardest part of programming is actually finding and squashinghttps://realpython.com/lessons/debugging/#t=12.96
the bugs. print() is a quick and easy way to help you hunt these things down to tellhttps://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:23https://realpython.com/lessons/debugging/#t=23.07
It’s jokingly sometimes referred to as caveman debugging because it’s a simplehttps://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 youhttps://realpython.com/lessons/debugging/#t=29.7
debug, I need to have some code to debug. The method on the screen at the momenthttps://realpython.com/lessons/debugging/#t=34.47
generates a Roman numeralhttps://realpython.com/lessons/debugging/#t=38.88
and it makes an assumption that it’s a four-digit Roman numeral, because it’s forhttps://realpython.com/lessons/debugging/#t=40.59
creating the copyright year in Roman numeralshttps://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:52https://realpython.com/lessons/debugging/#t=52.05
There’s a dictionary at the top that declares the common letters that are usedhttps://realpython.com/lessons/debugging/#t=52.05
in Roman numerals. Start with a divisor of 1000, essentiallyhttps://realpython.com/lessons/debugging/#t=55.5
assuming that our number is going to be a four-digit year. And then it loopshttps://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 hashhttps://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:31https://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 usedhttps://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:52https://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:04https://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 seehttps://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:20https://realpython.com/lessons/debugging/#t=140.04
The first one here at line 6 will tell me that the movie_year() has been calledhttps://realpython.com/lessons/debugging/#t=140.04
and what number is being debugged, to make sure things are happening properly. Athttps://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 divisorhttps://realpython.com/lessons/debugging/#t=150.06
is. You’ll notice that I put a few spaces in here. I like to do thishttps://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:40https://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 calledhttps://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:02https://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:12https://realpython.com/lessons/debugging/#t=192.34
The first print() statement shows me that 2015 was called. The first iterationhttps://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:23https://realpython.com/lessons/debugging/#t=203.5
The next digit is a 0. Well, right off you’ll noticehttps://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 hundredshttps://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:43https://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:48https://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:57https://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 14https://realpython.com/lessons/debugging/#t=238.54
has an elif of < 5. The case for 5https://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:14https://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:26https://realpython.com/lessons/debugging/#t=266.98
Now—as expected—when I rerun it,https://realpython.com/lessons/debugging/#t=266.98
04:32https://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:37https://realpython.com/lessons/debugging/#t=277.3
Using print() as a quick tool to insert in your code and see what’s going on ishttps://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:49https://realpython.com/lessons/debugging/#t=289.06
Adding print() statements to server side codehttps://realpython.com/lessons/debugging/#t=289.06
isn’t going to be particularly helpful ifhttps://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 longhttps://realpython.com/lessons/debugging/#t=296.62
running services, you need to get at informationhttps://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:10https://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:19https://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:32https://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 manipulatinghttps://realpython.com/lessons/debugging/#t=349.81
your logs.https://realpython.com/lessons/debugging/#t=353.38
05:55https://realpython.com/lessons/debugging/#t=355.09
So, here’s a simple function that counts the number of lowercase letters insidehttps://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 thehttps://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 intohttps://realpython.com/lessons/debugging/#t=364.22
logging is something called basicConfig().https://realpython.com/lessons/debugging/#t=369.08
06:11https://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 momenthttps://realpython.com/lessons/debugging/#t=373.73
specifies the stream to be stdout (standard out).https://realpython.com/lessons/debugging/#t=375.62
06:18https://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:22https://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:30https://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:39https://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:45https://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:52https://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 thehttps://realpython.com/lessons/debugging/#t=414.35
logs to easily distinguish between where a particular logging statement camehttps://realpython.com/lessons/debugging/#t=419.03
from.https://realpython.com/lessons/debugging/#t=423.11
07:05https://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 thehttps://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 forhttps://realpython.com/lessons/debugging/#t=441.98
injecting content inside of a string.https://realpython.com/lessons/debugging/#t=447.35
07:30https://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 thehttps://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:46https://realpython.com/lessons/debugging/#t=466.01
Importing the method, calling the method.https://realpython.com/lessons/debugging/#t=466.01
07:52https://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:07https://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:12https://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 callhttps://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:28https://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:33https://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 logshttps://realpython.com/lessons/debugging/#t=517.22
are the exception. You’ll notice in line 12https://realpython.com/lessons/debugging/#t=521.929
that I’m passing in the string for formattinghttps://realpython.com/lessons/debugging/#t=525.65
and then the attributes into the logging call itself, rather than the usualhttps://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:56https://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:12https://realpython.com/lessons/debugging/#t=552.03
That means when the debugger is set to INFO, this .debug() callhttps://realpython.com/lessons/debugging/#t=552.03
doesn’t actually create the string by passing the letter object into this stringhttps://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:24https://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 argumenthttps://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 veryhttps://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:43https://realpython.com/lessons/debugging/#t=583.95
The basicConfig() mechanism that I showed you is the easiest way to get up andhttps://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 smallhttps://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 inhttps://realpython.com/lessons/debugging/#t=593.97
earlier lessons with the configuration of a logger.https://realpython.com/lessons/debugging/#t=599.07
10:02https://realpython.com/lessons/debugging/#t=602.82
This format string uses the ANSI escape to bold the function name inside of thehttps://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:21https://realpython.com/lessons/debugging/#t=621.06
The basicConfig() call that you saw earlier does a version of these four stepshttps://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’vehttps://realpython.com/lessons/debugging/#t=630.45
talked about, and useful libraries you can take advantage of that can help you dohttps://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, 2020https://realpython.com/lessons/debugging/#comment-a115f5c9-42f0-4248-a7ed-108e4408aa59
July 7, 2020https://realpython.com/lessons/debugging/#comment-59007129-83fc-4edf-a474-9f2389e6473e
Jan. 17, 2021https://realpython.com/lessons/debugging/#comment-30ce4fcc-87b1-4a46-b530-57fadd7f28a2
Jan. 19, 2021https://realpython.com/lessons/debugging/#comment-b977a88e-704e-4827-837c-f828982a1de0
Become a Memberhttps://realpython.com/account/join/
https://realpython.com/lessons/mocking-print-unit-tests/
Overviewhttps://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 Policyhttps://realpython.com/privacy-policy/

Viewport: width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover

Robots: max-image-preview:large


URLs of crawlers that visited me.