Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: The Python print() Function: Go Beyond the Basics Show
If you’re like most Python users, including me, then you probably started your Python journey by learning about Keep reading to take full advantage of this seemingly boring and unappreciated little function. This tutorial will get you up to speed with using Python By the end of this tutorial, you’ll know how to:
If you’re a complete beginner, then you’ll benefit most from reading the first part of this tutorial, which illustrates the essentials of printing in Python. Otherwise, feel free to skip that part and jump around as you see fit. Printing in a NutshellLet’s jump in by looking at a few real-life examples of printing in Python. By the end of this section, you’ll know every possible way of calling Calling print()The simplest example of using Python You don’t pass any arguments, but you still need to put empty parentheses at the end, which tell Python to actually execute the function rather than just refer to it by name. This will produce an invisible newline character, which in turn will cause a blank line to appear on your screen. You can call A newline character is a special control character used to indicate the end of a line (EOL). It usually doesn’t have a visible representation on the screen, but some text editors can display such non-printable characters with little graphics. The word “character” is somewhat of a misnomer in this case, because a newline is often more than one character long. For example, the Windows operating system, as well as the HTTP protocol, represent newlines with a pair of characters. Sometimes you need to take those differences into account to design truly portable programs. To find out what constitutes a newline in your operating system, use Python’s built-in This will immediately tell you that Windows and DOS represent the newline as a sequence of >>>
On Unix,
Linux, and recent versions of macOS, it’s a single >>>
The classic Mac OS X, however, sticks to its own “think different” philosophy by choosing yet another representation: >>>
Notice how these characters appear in string literals. They use
special syntax with a preceding backslash ( Most programming languages come with a predefined set of escape sequences for special characters such as these:
The last two are reminiscent of mechanical typewriters, which required two separate commands to insert a newline. The first command would move the carriage back to the beginning of the current line, while the second one would advance the roll to the next line. By comparing the corresponding ASCII character codes, you’ll see that putting a backslash in front of a character changes its meaning completely. However, not all characters allow for this–only the special ones. To compare ASCII character codes, you may want to use the built-in >>>
Keep in mind that, in order to form a correct escape sequence, there must be no space between the backslash character and a letter! As you just saw, calling You can use Python’s string literals to visualize these two:
The first one is one character long, whereas the second one has no content. In a more common scenario, you’d want to communicate some message to the end user. There are a few ways to achieve this. First, you may pass a string literal directly to >>>
This will print the message verbatim onto the screen. String literals in Python can be enclosed either in single quotes ( For example, you can’t use double quotes for the literal and also include double quotes inside of it, because that’s ambiguous for the Python interpreter:
What you want to do is enclose the text, which contains double quotes, within single quotes:
The same trick would work the other way around:
Alternatively, you could use escape character sequences mentioned earlier, to make Python treat those internal double quotes literally as part of the string literal:
Escaping is fine and dandy, but it can sometimes get in the way. Specifically, when you need your string to contain relatively many backslash characters in literal form. One classic example is a file path on Windows:
Notice how each backslash character needs to be escaped with yet another backslash. This is even more prominent with regular expressions, which quickly get convoluted due to the heavy use of special characters:
Fortunately, you can turn off character escaping entirely with the help of raw-string literals. Simply prepend an
That’s much better, isn’t it? There are a few more prefixes that give special meaning to string literals in Python, but you won’t get into them here. Lastly, you can define multi-line string literals by enclosing them between Here’s an example:
To prevent an initial newline, simply put the text right after the opening
You can also use a backslash to get rid of the newline:
To remove indentation from a multi-line string, you might take advantage of the built-in >>>
This will take care of unindenting paragraphs for you. There are also a few other useful functions in Secondly, you could extract that message into its own variable with a meaningful name to enhance readability and promote code reuse: >>>
Lastly, you could pass an expression, like string concatenation, to be evaluated before printing the result: >>>
In fact, there are a dozen ways to format messages in Python. I highly encourage you to take a look at f-strings, introduced in Python 3.6, because they offer the most concise syntax of them all: >>>
Moreover, f-strings will prevent you from making a common mistake, which is forgetting to type cast concatenated operands. Python is a strongly typed language, which means it won’t allow you to do this: >>>
That’s wrong because adding numbers to strings doesn’t make sense. You need to explicitly convert the number to string first, in order to join them together: >>>
Unless you handle such errors yourself, the Python interpreter will let you know about a problem by showing a traceback. As with any function, it doesn’t matter whether you pass a literal, a variable, or an expression. Unlike many other functions, however,
So far, you only looked at the string, but how about other data types? Let’s try literals of different built-in types and see what comes out: >>>
Watch out for the How does Later in this tutorial, you’ll learn how to use this mechanism for printing custom data types such as your classes. Okay, you’re now able to call To achieve the same result in the previous language generation, you’d normally want to drop the parentheses enclosing the text:
That’s because For example, parentheses enclosing a single expression or a literal are optional. Both instructions produce the same result in Python 2: >>>
Round brackets are actually part of the expression rather than the On the other hand, putting parentheses around multiple items forms a tuple: >>>
This is a known source of confusion. In fact, you’d also get a tuple by appending a trailing comma to the only item surrounded by parentheses: >>>
The bottom line is that you shouldn’t call Separating Multiple ArgumentsYou saw However, it turns out that this function can accept any number of positional arguments, including zero, one, or more arguments. That’s very handy in a common case of message formatting, where you’d want to join a few elements together. Arguments can be passed to a function in one of several ways. One way is by explicitly naming the arguments when you’re calling the function, like this: >>>
Since arguments can be uniquely identified by name, their order doesn’t matter. Swapping them out will still give the same result: >>>
Conversely, arguments passed without names are identified by their position. That’s why positional arguments need to follow strictly the order imposed by the function signature: >>>
Let’s have a look at this example: >>>
Notice that it also took care of proper type casting by implicitly calling >>>
Apart from accepting a variable number of positional arguments, Let’s focus on It has to be either a string or >>>
If you wanted to suppress the separator completely, you’d have to pass an empty string ( >>>
You may want >>>
A more useful example of the >>>
Remember that the separator comes between the elements, not around them, so you need to account for that in one way or another: >>>
Specifically, you can insert a slash character ( One more interesting example could be exporting data to a comma-separated values (CSV) format: >>>
This wouldn’t handle edge cases such as escaping commas correctly, but for simple use cases, it should do. The line
above would show up in your terminal window. In order to save it to a file, you’d have to redirect the output. Later in this section, you’ll see how to use Finally, the >>>
In the upcoming subsections, you’ll explore the remaining
keyword arguments of the To print multiple elements in Python 2, you must drop the parentheses around them, just like before: >>>
If you kept them, on the other hand, you’d be passing a single tuple element to the >>>
Moreover, there’s no way of altering the default separator of joined elements in Python 2, so one workaround is to use string interpolation like so: >>>
That was the default way of formatting strings until the Preventing Line BreaksSometimes you don’t want to end your message with a trailing newline so that subsequent calls to
Many programming
languages expose functions similar to Here are a few examples of syntax in such languages:
In contrast, Python’s In terms of semantics, the
Now you understand what’s happening under the hood when you’re calling To disable the newline, you must specify an empty string through the
Even though these are two separate
However, after the second call to
As with
These three instructions will output a single line of text:
You can mix the two keyword arguments:
Not only do you get a single line of text, but all items are separated with a comma:
There’s nothing to stop you from using the newline character with some extra padding around it:
It would print out the following piece of text:
As you can see, the You’re getting more acquainted with printing in Python, but there’s still a lot of useful information ahead. In the upcoming subsection, you’ll learn how to intercept and redirect the Preventing a line break in Python 2 requires that you append a trailing comma to the expression: However, that’s not ideal because it also adds an unwanted space, which would translate to
Notice there’s a space between the words In order to get the expected result, you’d need to use one of the tricks explained later, which is either importing the
This will print the correct output without extra space: While using the Printing to a FileBelieve it or
not,
In addition to this, there are three standard streams provided by the operating system:
Standard output is what you see in the terminal when you run various command-line programs including your own Python scripts:
Unless otherwise instructed,
That’s called stream redirection. The standard error is similar to Some programs use different coloring to distinguish between messages printed to While both In Python, you can access all standard streams through the built-in >>>
As you can see, these predefined values resemble file-like objects with By default,
This will make your code immune to stream redirection at the operating system level, which might or might not be desired. For more information on working with files in Python, you can check out Reading and Writing Files in Python (Guide). Note that
Instead of a real file existing somewhere in your file system, you can provide a fake one, which would reside in your computer’s memory. You’ll use this technique later for mocking >>>
If you got to this point, then you’re left with only one keyword argument in There’s a special syntax in Python 2 for replacing the default
Because strings and bytes are represented with the same
Although, there’s a problem with character encoding. The >>>
Notice how non-Latin characters must be escaped in both Unicode and string literals to avoid a syntax error. Take a look at this example:
Alternatively, you could specify source code encoding according to PEP 263 at the top of the file, but that wasn’t the best practice due to portability issues:
Your best bet is to encode the Unicode string just before printing it. You can do this manually:
However, a more convenient option is to use the built-in
It’ll take care of making appropriate conversions when you need to read or write files. Buffering print() CallsIn the previous subsection, you learned that Imagine you were writing a countdown timer, which should append the remaining time to the same line every second: Your first attempt may look something like this:
As long as the Unexpectedly, instead of counting down every second, the program idles wastefully for three seconds, and then suddenly prints the entire line at once: That’s because the operating system buffers subsequent writes to the standard output in this case. You need to know that there are three kinds of streams with respect to buffering:
Unbuffered is self-explanatory, that is, no buffering is taking place, and all writes have immediate effect. A line-buffered stream waits before firing any I/O calls until a line break appears somewhere in the buffer, whereas a block-buffered one simply allows the buffer to fill up to a certain size regardless of its content. Standard output is both line-buffered and block-buffered, depending on which event comes first. Buffering helps to reduce the number of expensive I/O calls. Think about sending messages over a high-latency network, for example. When you connect to a remote server to execute commands over the SSH protocol, each of your keystrokes may actually produce an individual data packet, which is orders of magnitude bigger than its payload. What an overhead! It would make sense to wait until at least a few characters are typed and then send them together. That’s where buffering steps in. On the other hand, buffering can sometimes have undesired effects as you just saw with the countdown example. To fix
it, you can simply tell
That’s all. Your countdown should work as expected now, but don’t take my word for it. Go ahead and test it to see the difference. Congratulations! At this point, you’ve seen examples of calling There isn’t an easy way to flush the stream in Python 2, because the
Alternatively, you could disable buffering of the standard streams either by providing the
Note that >>>
What you’re seeing here is a docstring of the Printing Custom Data TypesUp until now, you only dealt with built-in data types such as strings and numbers, but you’ll often want to print your own abstract data types. Let’s have a look at different ways of defining them. For simple objects without any logic, whose purpose
is to carry data, you’ll typically take advantage of >>>
That’s great as long as holding data is enough, but in order to add behaviors to the
If you now create an instance of the >>>
It’s the default representation of objects, which comprises their address in memory, the corresponding class name and a module in which they were defined. You’ll fix that in a bit, but just for the record, as a
quick workaround you could combine
Your That’s better than a plain It’s true that designing immutable data types is desirable, but in many cases, you’ll want them to allow for change, so you’re back with regular classes again. From earlier subsections, you already know that >>>
The first one is recommended to return a short, human-readable text, which includes information from the most relevant attributes. After all, you don’t want to expose sensitive data, such as user passwords, when printing objects. However, the other one should provide complete information about an object, to allow for restoring its state from a string. Ideally, it should return valid Python code, so that you can pass it directly to
>>>
Notice the use of another built-in function, Python gives you a lot of freedom when it comes to defining your own data types if none of the built-in ones meet your needs. Some of them, such as named tuples and data classes, offer string representations that look good without requiring any work on your part. Still, for the most flexibility, you’ll have to define a class and override its magic methods described above. The semantics of Here’s an example of the same
As you can see, this implementation delegates some work to avoid duplication by calling the built-in Both The >>>
However, if you ran the same code on a system with UTF-8 encoding, then you’d get the proper spelling of a popular Russian name: >>>
It’s recommended to convert strings to Unicode as early as possible, for example, when you’re reading data from a file, and use it consistently everywhere in your code. At the same time, you should encode Unicode back to the chosen character set right before presenting it to the user. It seems as if you have more control over string representation of objects in Python 2 because there’s no magic >>>
Using the built-in Understanding Python print()You know how to use Print Is a Function in Python 3You’ve seen that >>>
It’s always available in the global namespace so that you can call it directly, but you can also access it through a module from the standard library: >>>
This way, you can avoid name collisions with custom functions. Let’s say you
wanted to redefine >>>
Now you have two separate printing functions just like in the Java programming language. You’ll define custom On the other hand, >>>
Such
functions are, in fact, procedures or subroutines that you call to achieve some kind of side-effect, which ultimately is a change of a global state. In the case of Because Besides, functions are easier to extend. Adding a new feature to a function is as easy as adding another keyword argument, whereas changing the language to support that new feature is much more cumbersome. Think of stream redirection or buffer flushing, for example. Another benefit of
Here, the Composition allows you to combine a few functions into a new one of the same kind. Let’s see this in action by specifying a custom >>>
This custom function uses partial functions to achieve the desired effect. It’s an advanced concept borrowed from the functional programming paradigm, so you don’t need to go too deep into that topic for now. However, if you’re
interested in this topic, I recommend taking a look at the Unlike statements, functions are values. That means you can mix them with expressions, in particular, lambda expressions. Instead of defining a full-blown function to replace >>>
However, because a lambda expression is defined in place, there’s no way of referring to it elsewhere in the code. Another kind of expression is a ternary conditional expression: >>>
Python has both conditional statements and
conditional expressions. The latter is evaluated to a single value that can be assigned to a variable or passed to a function. In the example above, you’re interested in the side-effect rather than the value, which evaluates to As you can see, functions allow for an elegant and extensible solution, which is consistent with
the rest of the language. In the next subsection, you’ll discover how not having print Was a Statement in Python 2A statement is an instruction that may evoke a side-effect when executed but never evaluates to a value. In other words, you wouldn’t be able to print a statement or assign it to a variable like this:
That’s a syntax error in Python 2. Here are a few more examples of statements in Python:
Statements are usually comprised of reserved keywords such as Furthermore, you can’t print from anonymous functions, because statements aren’t accepted in lambda expressions: >>>
The syntax of the >>>
At other times they change how the message is printed: >>>
String concatenation can raise a >>>
Compare this with similar code in Python 3, which leverages sequence unpacking: >>>
There aren’t any keyword arguments for common tasks such as flushing the buffer or stream redirection. You need to remember the quirky syntax instead. Even the built-in >>>
Trailing newline removal doesn’t work quite right, because it adds an unwanted space. You can’t compose multiple The list of problems goes on and on. If you’re curious, you can jump back to the previous section and look for more detailed explanations of the syntax in Python 2. However, you can mitigate some of those problems with a much simpler approach. It turns out the To enable the
From now on the Other than that, it doesn’t spare you from managing character encodings properly. Here’s an example of calling the >>>
You now have an idea of how printing in Python evolved and, most importantly, understand why these backward-incompatible changes were necessary. Knowing this will surely help you become a better Python programmer. Printing With StyleIf you thought that printing was only about lighting pixels up on the screen, then technically you’d be right. However, there are ways to make it look cool. In this section, you’ll find out how to format complex data structures, add colors and other decorations, build interfaces, use animation, and even play sounds with text! Pretty-Printing Nested Data StructuresComputer languages allow you to represent data as well as executable code in a structured way. Unlike Python, however, most languages give you a lot of freedom in using whitespace and formatting. This can be useful, for example in compression, but it sometimes leads to less readable code. Pretty-printing is about making a piece of data or code look more appealing to the human eye so that it can be understood more easily. This is done by indenting certain lines, inserting newlines, reordering elements, and so forth. Python comes
with the If you don’t care
about not having access to the original >>>
Personally, I like to have both functions at my fingertips, so I’d rather use something like
At first glance, there’s hardly any difference between the two functions, and in some cases there’s virtually none: >>>
That’s because >>>
The function applies reasonable formatting to improve readability, but you can customize it even further with a couple of parameters. For example, you may limit a deeply nested hierarchy by showing an ellipsis below a given level: >>>
The ordinary >>>
However, >>>
The last element in the list is the same object as the entire list.
Dictionaries often represent JSON data, which is widely used on the Internet. To correctly serialize a dictionary into a valid JSON-formatted string, you can take advantage of the >>>
Notice, however, that you need to handle
printing yourself, because it’s not something you’d typically want to do. Similarly, the Surprisingly, the signature of Adding Colors With ANSI Escape SequencesAs personal computers got more sophisticated, they had better graphics and could display more colors. However, different vendors had their own idea about the API design for controlling it. That changed a few decades ago when people at the American National Standards Institute decided to unify it by defining ANSI escape codes. Most of today’s terminal emulators support this standard to some degree. Until recently, the Windows operating system was a notable exception. Therefore, if you want the best portability, use the To check if your terminal understands a subset of the ANSI escape sequences, for example, related to colors, you can try using the following command: My default terminal on Linux says it can display 256 distinct colors, while xterm gives me only 8. The command would return a negative number if colors were unsupported. ANSI escape sequences are like a markup language for the terminal. In HTML you work with tags, such as As its name implies, a sequence must begin with the non-printable Esc character, whose ASCII value is 27, sometimes denoted as >>>
Additionally, you can obtain it with the The most common ANSI escape sequences take the following form:
The numeric code can be one or more numbers separated with a semicolon, while the character code is just one letter. Their specific meaning is defined by the ANSI standard. For example, to reset all formatting, you would type one of the following commands, which use the code zero and the letter
At the other end of the spectrum, you have compound code values. To set foreground and background with RGB channels, given that your terminal supports 24-bit depth, you could provide multiple numbers:
It’s not just text color that you can set with the ANSI escape codes. You can, for example, clear and scroll the terminal window, change its background, move the cursor around, make the text blink or decorate it with an underline. In Python, you’d probably write a helper function to allow for wrapping arbitrary codes into a sequence: >>>
This would make the word However, there are higher-level abstractions over ANSI escape codes, such as the mentioned Building Console User InterfacesWhile playing with ANSI escape codes is undeniably a ton of fun, in the real world you’d rather have more abstract building blocks to put together a user interface. There are a few libraries that provide such a high level of control over the terminal, but
Primarily, it allows you to think in terms of independent graphical widgets instead of a blob of text. Besides, you get a lot of freedom in expressing your inner artist, because it’s really like painting a blank canvas. The library hides the complexities of having to deal with different terminals. Other than that, it has great support for keyboard events, which might be useful for writing video games. How about making a retro snake game? Let’s create a Python snake simulator: First, you
need to import the
Note, the function must accept a reference to the screen object, also known as If you run this program now, you won’t see any effects, because it terminates immediately. However, you can add a small delay to have a sneak peek:
This time the screen went completely blank for a second, but the cursor was still blinking. To hide it, just call one of the configuration functions defined in the module:
Let’s define the snake as a list of points in screen coordinates:
The head of the snake is always the first element in the list, whereas the tail is the last one. The initial shape of the snake is horizontal, starting from the top-left corner of the screen and facing to the right. While its y-coordinate stays at zero, its x-coordinate decreases from head to tail. To draw the snake, you’ll start with the head and then follow with the remaining segments. Each segment carries
Again, if you run this code now, it won’t display anything, because you must explicitly refresh the screen afterward:
You want to move the snake in one of four directions, which can be defined as vectors. Eventually, the direction will change in response to an arrow keystroke, so you may hook it up to the library’s key codes:
How does a snake move? It turns out that only its head really moves to a new location, while all other segments shift towards it. In each step, almost all segments remain the same, except for the head and the tail. Assuming the snake isn’t growing, you can remove the tail and insert a new head at the beginning of the list:
To get the new coordinates of the head, you need to add the direction vector to it. However, adding tuples in Python results in a bigger tuple instead of the algebraic sum of the corresponding vector components. One way to fix this is by using the built-in The direction will change on a keystroke, so you need to call
By default, however,
You’re almost done, but there’s just one last thing left. If you now loop this code, the snake will appear to be growing instead of moving. That’s because you have to erase the screen explicitly before each iteration. Finally, this is all you need to play the snake game in Python:
This is merely scratching the surface of the possibilities that the Living It Up With Cool AnimationsNot only can animations make the user interface more appealing to the eye, but they also improve the overall user experience. When you provide early feedback to the user, for example, they’ll know if your program’s still working or if it’s time to kill it. To animate text in the terminal, you have to be able to freely move the cursor around. You can do this with one of the tools mentioned previously, that is ANSI escape codes or the If the animation can be constrained to a single line of text, then you might be interested in two special escape character sequences:
The first one moves the cursor to the beginning of the line, whereas the second one moves it only one character to the left. They both work in a non-destructive way without overwriting text that’s already been written. Let’s take a look at a few examples. You’ll often want to display some kind of a spinning wheel to indicate a work in progress without knowing exactly how much time’s left to finish: Many command line tools use this trick while downloading data over the network. You can make a really simple stop motion animation from a sequence of characters that will cycle in a round-robin fashion:
The loop gets the next character to print, then moves the cursor to the beginning of the line, and overwrites whatever there was before without adding a newline. You don’t want extra space between positional arguments, so separator argument must be blank. Also, notice the use of Python’s raw strings due to backslash characters present in the literal. When you know the remaining time or task completion percentage, then you’re able to show an animated progress bar: First, you need to calculate how many hashtags to display and how many blank spaces to insert. Next, you erase the line and build the bar from scratch:
As before, each request for update repaints the entire line. Making Sounds With print()If you’re old enough to remember computers with a PC speaker, then you must also remember their distinctive beep sound, often used to indicate hardware problems. They could barely make any more noises than that, yet video games seemed so much better with it. Today you can still take advantage of this small loudspeaker, but chances are your laptop didn’t come with one. In such a case, you can enable terminal bell emulation in your shell, so that a system warning sound is played instead. Go ahead and type this command to see if your terminal can play a sound: This would normally print text, but the Similarly, you can print this character in Python. Perhaps in a loop to form some kind of melody. While it’s only a single note, you can still vary the length of pauses between consecutive instances. That seems like a perfect toy for Morse code playback! The rules are the following:
According to those rules, you could be “printing” an SOS signal indefinitely in the following way:
In Python, you can implement it in merely ten lines of code:
Maybe you could even take it one step further and make a command line tool for translating text into Morse code? Either way, I hope you’re having fun with this! Mocking Python print() in Unit TestsNowadays, it’s expected that you ship code that meets high quality standards. If you aspire to become a professional, you must learn how to test your code. Software testing is especially important in dynamically typed languages, such as Python, which don’t have a compiler to warn you about obvious mistakes. Defects can make their way to the production environment and remain dormant for a long time, until that one day when a branch of code finally gets executed. Sure, you have linters, type checkers, and other tools for static code analysis to assist you. But they won’t tell you whether your program does what it’s supposed to do on the business level. So, should you be testing You can test behaviors by mocking real objects or functions. In this case, you want to mock Mocking in Python can be done twofold. First, you can take the traditional path of statically-typed languages by employing dependency injection. This may sometimes require you to change the code under test, which isn’t always possible if the code is defined in an external library:
This is the same example I used in an earlier section to talk about function composition. It basically allows for substituting >>>
Calling this mock makes it save the last message in an attribute, which you can inspect later, for example in an In a slightly alternative solution, instead of replacing the entire >>>
This time the function explicitly calls However, a more Pythonic way of mocking objects takes advantage of the built-in What monkey patching does is alter implementation dynamically at runtime. Such a change is visible globally, so it may have unwanted consequences. In practice, however, patching only affects the code for the duration of test execution. To mock
This will automatically create the mock for you and inject it to the test function. However, you need to declare that your test function accepts a mock now. The underlying mock object has lots of useful methods and attributes for verifying behavior. Did you notice anything peculiar about that code snippet? Despite injecting a mock to the function, you’re not calling it directly, although you could. That injected mock is only used to make assertions afterward and maybe to prepare the context before running the test. In real life, mocking helps to isolate the code under test by removing dependencies such as a database connection. You rarely call mocks in a test, because that doesn’t make much sense. Rather, it’s other pieces of code that call your mock indirectly without knowing it. Here’s what that means:
The code under test is a function that prints a greeting. Even though it’s a fairly simple function, you can’t test it easily because it doesn’t return a value. It has a side-effect. To eliminate that side-effect, you need to mock the dependency out. Patching lets you avoid making changes to the original function, which can remain agnostic about There are many reasons for testing software. One of them is looking for bugs. When you write tests, you often want to get rid of the You can’t monkey patch the
Let’s examine them one by one. Stream redirection is almost identical to the example you saw earlier: >>>
There are only two differences.
First, the syntax for stream redirection uses chevron ( Patching the standard output from the
First of all, remember to install the Secondly, the Finally, a single The last option you have is importing
Again, it’s nearly
identical to Python 3, but the print() DebuggingIn this section, you’ll take a look at the available tools for debugging in Python, starting from a humble TracingAlso known as print debugging or caveman debugging, it’s the most basic form of debugging. While a little bit old-fashioned, it’s still powerful and has its uses. The idea is to follow the path of program execution until it stops abruptly, or gives incorrect results, to identify the exact instruction with a problem. You do that by inserting print statements with words that stand out in carefully chosen places. Take a look at this example, which manifests a rounding error: >>>
As you can see, the function doesn’t return the expected value of In this case, the problem lies in how floating point numbers are represented in computer memory. Remember that numbers are stored in binary form. Decimal value of For more information on rounding numbers in Python, you can check out How to Round Numbers in Python. This method is simple and intuitive and will work in pretty much every programming language out there. Not to mention, it’s a great exercise in the learning process. On the other hand, once you master more advanced techniques, it’s hard to go back, because they allow you to find bugs much quicker. Tracing is a laborious manual process, which can let even more
errors slip through. The build and deploy cycle takes time. Afterward, you need to remember to meticulously remove all the Besides, it requires you to make changes in the code, which isn’t always possible. Maybe you’re debugging an application running in a remote web server or want to diagnose a problem in a post-mortem fashion. Sometimes you simply don’t have access to the standard output. That’s precisely where logging shines. LoggingLet’s pretend for a minute that you’re running an e-commerce website. One day, an angry customer makes a phone call complaining about a failed transaction and saying he lost his money. He claims to have tried purchasing a few items, but in the end, there was some cryptic error that prevented him from finishing that order. Yet, when he checked his bank account, the money was gone. You apologize sincerely and make a refund, but also don’t want this to happen again in the future. How do you debug that? If only you had some trace of what happened, ideally in the form of a chronological list of events with their context. Whenever you find yourself doing print debugging, consider turning it into permanent log messages. This may help in situations like this, when you need to analyze a problem after it happened, in an environment that you don’t have access to. There are sophisticated tools for log aggregation and searching, but at the most basic level, you can think of logs as text files. Each line conveys detailed information about an event in your system. Usually, it won’t contain personally identifying information, though, in some cases, it may be mandated by law. Here’s a breakdown of a typical log record:
As you can see, it has a structured form. Apart from a descriptive message, there are a few customizable fields, which provide the context of an event. Here, you have the exact date and time, the log level, the logger name, and the thread name. Log levels allow you to filter messages quickly to reduce noise. If you’re looking for an error, you don’t want to see all the warnings or debug messages, for example. It’s trivial to disable or enable messages at certain log levels through the configuration, without even touching the code. With logging, you can keep your debug messages separate from the standard output. All the log messages go to the standard error stream by default, which can conveniently show up in different colors. However, you can redirect log messages to separate files, even for individual modules! Quite commonly, misconfigured logging can lead to running out of space on the server’s disk. To prevent that, you may set up log rotation, which will keep the log files for a specified duration, such as one week, or once they hit a certain size. Nevertheless, it’s always a good practice to archive older logs. Some regulations enforce that customer data be kept for as long as five years! Compared to other programming languages, logging in Python is simpler, because the
You can call functions defined at the module level, which are hooked to the root logger, but more the common practice is to obtain a dedicated logger for each of your source files:
The advantage of using custom loggers is more fine-grain control. They’re usually named after the module they were defined in through the One last reason to switch
from the DebuggingThe truth is that neither tracing nor logging can be considered real debugging. To do actual debugging, you need a debugger tool, which allows you to do the following:
A crude debugger that runs in the terminal, unsurprisingly named However, it doesn’t come with a graphical interface, so using
Otherwise, you can set up a breakpoint directly in the code, which will pause the execution of your script and drop you into the debugger. The old way of doing this required two steps: >>>
This shows up an interactive prompt, which might look intimidating at first. However, you can still type native Python at this point to examine or modify the state of local variables. Apart from that, there’s really only a handful of debugger-specific commands that you want to use for stepping through the code. Since Python 3.7, you can also call the built-in
You’re probably going to use a visual debugger integrated with a code editor for the most part. PyCharm has an excellent debugger, which boasts high performance, but you’ll find plenty of alternative IDEs with debuggers, both paid and free of charge. Debugging isn’t the proverbial silver bullet. Sometimes logging or tracing will be a better solution. For example, defects that are hard to reproduce, such as race conditions, often result from temporal coupling. When you stop at a breakpoint, that little pause in program execution may mask the problem. It’s kind of like the Heisenberg principle: you can’t measure and observe a bug at the same time. These methods aren’t mutually exclusive. They complement each other. Thread-Safe PrintingI
briefly touched upon the thread safety issue before, recommending Thread safety means that a piece of code can be safely shared between multiple threads of execution. The simplest strategy for ensuring thread-safety is by sharing immutable objects only. If threads can’t modify an object’s state, then there’s no risk of breaking its consistency. Another method takes advantage of local memory, which makes each thread receive its own copy of the same object. That way, other threads can’t see the changes made to it in the current thread. But that doesn’t solve the problem, does it? You often want your threads to cooperate by being able to mutate a shared resource. The most common way of synchronizing concurrent access to such a resource is by locking it. This gives exclusive write access to one or sometimes a few threads at a time. However, locking is expensive and reduces concurrent throughput, so other means for controlling access have been invented, such as atomic variables or the compare-and-swap algorithm. Printing isn’t thread-safe in Python. The In practice, however, that doesn’t happen. No matter how hard you try, writing to the standard output seems to be atomic. The only problem that you may sometimes observe is with messed up line breaks:
To simulate this, you can increase the likelihood of a context switch by making the underlying
First, you need to store the original If you read the mocking section before, then you may already have an idea of why printing misbehaves like
that. Nonetheless, to make it crystal clear, you can capture values fed into your
Even though You can make the newline character become an integral part of the message by handling it manually:
This will fix the output:
Notice, however, that the
A truly thread-safe version of the
You can put that function in a module and import it elsewhere:
Now,
despite making two writes per each
I added comments to indicate how the lock is limiting access to the shared resource. Conversely, the >>>
It’s another
reason why you might not want to use the Python Print CounterpartsBy now, you know a lot of what there is to know about Built-InPython comes with a built-in function for accepting input from the user, predictably called >>>
The function always returns a string, so you might need to parse it accordingly:
The prompt parameter is completely optional, so nothing will show if you skip it, but the function will still work: >>>
Nevertheless, throwing in a descriptive call to action makes the user experience so much better. Asking the user for a password with >>>
The >>>
Python’s built-in functions for handling the standard input are quite limited. At the same time, there are plenty of third-party packages, which offer much more sophisticated tools. Third-PartyThere are external Python packages out there that allow for building complex graphical interfaces specifically to collect data from the user. Some of their features include:
Demonstrating such tools is outside of the scope of this article, but you may want to try them out. I personally got to know about some of those through the Python Bytes Podcast. Here they are:
Nonetheless, it’s worth mentioning a command line tool called Let’s assume you wrote a command-line interface that understands three instructions, including one for adding numbers:
At first glance, it seems like a typical prompt when you run it:
But as soon as you make a mistake and want to fix it, you’ll see that none of the function keys work as expected. Hitting the Left arrow, for example, results in this instead of moving the cursor back:
Now, you can wrap the same script with the
Isn’t that great? ConclusionYou’re now armed with a body of knowledge about the Apart from that, you learned how to:
Now that you know all this, you can make interactive programs that communicate with users or produce data in popular file formats. You’re able to quickly diagnose problems in your code and protect yourself from them. Last but not least, you know how to implement the classic snake game. If you’re still thirsty for more information, have questions, or simply would like to share your thoughts, then feel free to reach out in the comments section below. Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: The Python print() Function: Go Beyond the Basics |