How to console log in Python

Learn how to console log in Python. Discover different methods, tips, real-world applications, and how to debug common errors.

How to console log in Python
Published on: 
Tue
Mar 17, 2026
Updated on: 
Tue
Mar 24, 2026
The Replit Team

For Python developers, console logs are a fundamental tool. They let you track program flow, debug issues, and observe application behavior without complex setups.

This article covers essential techniques to log information, from basic print() statements to advanced modules. You'll find practical tips, real world applications, and specific debug advice to improve your workflow.

Using the basic print() function

message = "Hello, World!"
print(message)
print("The value is:", 42)--OUTPUT--Hello, World!
The value is: 42

The print() function is the most direct way to output information to the console. It’s perfect for simple debugging because it's built-in and requires no setup. The example demonstrates its flexibility for inspecting program state without interrupting the flow.

  • You can pass a single variable, like message, to see its current value.
  • You can also pass multiple arguments, such as "The value is:" and 42. print() automatically converts different data types to strings and joins them with a space, simplifying how you create descriptive log messages.

Standard output techniques

While the basic print() function is a good starting point, Python provides more sophisticated methods for controlling your output's format and destination.

Using formatted strings with print()

name = "Alice"
age = 30
print(f"Name: {name}, Age: {age}")
print("Binary: {0:b}, Hex: {0:x}, Octal: {0:o}".format(42))--OUTPUT--Name: Alice, Age: 30
Binary: 101010, Hex: 2a, Octal: 52

Formatted strings give you more control over your console output. They let you embed variables directly into strings for cleaner, more readable logs—a big step up from concatenating multiple parts.

  • f-strings: Prefixing a string with an f, as in f"Name: {name}, Age: {age}", is a modern and highly readable way to insert variable values. The expressions inside the curly braces are evaluated and placed directly into the string.
  • The .format() method: This older method is also powerful. It lets you specify advanced format types, like converting the number 42 into its binary (:b), hexadecimal (:x), or octal (:o) forms.

Using the sys.stdout interface

import sys

sys.stdout.write("This is written to stdout\n")
sys.stdout.flush() # Force output to be written immediately
print("Output buffering level:", sys.stdout.line_buffering)--OUTPUT--This is written to stdout
Output buffering level: True

The sys.stdout object gives you direct access to Python's standard output stream—the same destination print() uses. Writing directly with sys.stdout.write() offers lower-level control but requires you to manage details like newlines (\n) manually.

  • The write() method sends a string directly to the console without extra formatting.
  • Calling flush() forces any buffered output to display immediately. It's essential when you need to see log messages in real time.
  • The line_buffering attribute simply shows if the stream is set to flush after every line, which is often the default.

Using the logging module

import logging

logging.basicConfig(level=logging.INFO)
logging.info("This is an informational message")
logging.warning("This is a warning message")
logging.error("This is an error message")--OUTPUT--INFO:root:This is an informational message
WARNING:root:This is a warning message
ERROR:root:This is an error message

For more structured application logging, Python’s logging module is a powerful step up from print(). It lets you categorize messages by severity. Using logging.basicConfig(level=logging.INFO) configures the logger to show any message with a severity of INFO or higher. This setup is great for filtering output based on your needs—for example, hiding detailed debug messages in a production environment.

  • logging.info() is used for general operational messages.
  • logging.warning() signals an unexpected event or a potential problem.
  • logging.error() indicates a more serious issue that has occurred.

Advanced console logging approaches

While built-in functions are a great start, you can create far more dynamic and readable output using specialized libraries for rich text, pretty-printing, and progress bars.

Enhanced output with the rich library

from rich.console import Console
from rich import print as rprint

console = Console()
console.print("Hello", "World", style="bold red")
rprint("[blue]Cool[/blue] [green]formatting[/green] [yellow]options[/yellow]!")--OUTPUT--Hello World
Cool formatting options!

The rich library is a powerful tool for creating visually appealing console output. It goes beyond simple text by letting you easily add colors and styles, which can make your logs much easier to read and understand at a glance.

  • The Console object’s print method can apply styles to entire lines of text, such as with style="bold red".
  • The library's special print function—aliased here as rprint—understands simple markup, letting you style individual words directly within a string, like with [blue]Cool[/blue].

Pretty printing complex data structures with pprint

import pprint

complex_data = {"users": [{"name": "John", "age": 30, "skills": ["Python", "JavaScript"]},
{"name": "Alice", "age": 25, "skills": ["Java", "C++"]}]}
pprint.pprint(complex_data, width=40, depth=2)--OUTPUT--{'users': [{'age': 30,
'name': 'John',
'skills': ['Python',
'JavaScript']},
{'age': 25,
'name': 'Alice',
'skills': ['Java', 'C++']}]}

When you're working with complex data structures like nested dictionaries, a standard print() can create a jumbled mess. The pprint module—short for "pretty-print"—solves this by automatically formatting the output to be human-readable. It sorts dictionary keys and wraps lines intelligently, making it much easier to inspect your data.

  • The width parameter controls the maximum line length, preventing your output from running off the screen.
  • Using depth limits how many levels of nesting are displayed, which is useful for getting a high-level overview of very large objects.

Creating progress indicators with tqdm

from tqdm import tqdm
import time

for i in tqdm(range(10), desc="Processing"):
time.sleep(0.1) # Simulate work
print("Task completed!")--OUTPUT--Processing: 100%|██████████| 10/10 [00:01<00:00, 9.90it/s]
Task completed!

The tqdm library is fantastic for adding progress bars to long-running loops with minimal effort. It gives you crucial visual feedback on tasks that might otherwise seem frozen, so you know your script is still working.

  • You simply wrap any iterable, like range(10), with the tqdm() function inside your for loop.
  • The library automatically handles drawing and updating the progress bar as the loop iterates.
  • You can add a custom label using the desc parameter, as shown with desc="Processing".

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. You can describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the logging techniques covered in this article, Replit Agent can turn them into production-ready tools:

  • Build a command-line utility that processes large files and uses a tqdm-style progress bar to show real-time status.
  • Create a server monitoring script that uses color-coded logs, similar to the rich library, to distinguish between info, warning, and error events.
  • Deploy an API data viewer that fetches complex JSON and uses pprint to format the output for easy debugging.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

Even with simple tools like print(), a few common pitfalls can trip you up while debugging your Python code.

  • Forgetting to convert types in print() concatenation
  • If you try to join a string and a number using the + operator, Python will raise a TypeError. While print() handles different types automatically when they are passed as separate arguments, string concatenation requires you to manually convert all parts to strings first.
  • Debugging multiple variables with print()
  • Simply printing multiple variables in a row can lead to a confusing jumble of output. Without labels, you won't know which value belongs to which variable. Using f-strings to add descriptive text makes your logs instantly understandable.
  • Misusing escape sequences in print() strings
  • A backslash in a string signals an escape sequence, where a character combination like \n is interpreted as a newline. This often causes problems with Windows file paths. To prevent this, you can use raw strings by adding an r before the opening quote.

Forgetting to convert types in print() concatenation

A classic mistake is using the + operator to join strings and numbers inside a print() statement. Unlike passing them as separate arguments, Python won't automatically convert the number, triggering a TypeError. The following code demonstrates this common pitfall.

age = 30
print("I am " + age + " years old")

The + operator fails because it can't join a string like "I am " with the integer variable age. Python doesn't automatically convert types during concatenation. The corrected code below demonstrates the proper approach.

age = 30
print("I am " + str(age) + " years old")
# Alternative better approach
print(f"I am {age} years old")

To fix the TypeError, you must explicitly convert non-string types before concatenating with the + operator. Wrapping the age variable in str() tells Python to treat it as a string. An even better solution is using an f-string, like f"I am {age} years old", which handles the conversion for you automatically and results in cleaner code. This error is common when building strings dynamically from different data types.

Debugging multiple variables with print()

Printing multiple variables with print() is a quick debugging trick, but it often creates a confusing jumble of values. Without labels, it's hard to tell which value belongs to which variable. The following code demonstrates this common issue.

x = 10
y = 20
z = x + y
print("Debug values:", x, y, z)
# Hard to tell which value is which

The output is just a series of numbers, making it easy to lose track of which value belongs to x, y, or z. This ambiguity quickly becomes unmanageable. See how the corrected code adds the necessary context.

x = 10
y = 20
z = x + y
print(f"Debug values: x={x}, y={y}, z={z}")

Using an f-string like f"Debug values: x={x}, y={y}, z={z}" solves the ambiguity by embedding both the variable's name and its value directly into the output. This makes your logs instantly clear, so you're not left guessing which number corresponds to which variable. This habit is especially helpful when debugging loops or functions where variable states change quickly, saving you time and preventing confusion. Your debugging process becomes much more efficient.

Misusing escape sequences in print() strings

A backslash (\) in a Python string isn't just a character; it signals an escape sequence. This means a combination like \n becomes a newline, which can mangle your output, especially with file paths. The following code demonstrates this common issue.

# Trying to print a filepath with backslashes
print("The file is located at: C:\Users\name\documents")

Python interprets the \U and \n in the file path as special characters, not literal backslashes. This corrupts the string before it's even printed. The corrected code below demonstrates how to handle this.

# Fix using raw strings
print(r"The file is located at: C:\Users\name\documents")
# Alternative fix using double backslashes
print("The file is located at: C:\\Users\\name\\documents")

To fix this, use a raw string by adding an r before the opening quote, like r"C:\Users...". This tells Python to treat backslashes as literal characters instead of escape sequences. Alternatively, you can escape each backslash by doubling it, as in "C:\\Users...". This issue is especially common when you're working with Windows file paths or regular expressions, so it's a good habit to use raw strings for them.

Real-world applications

Now that you can avoid common pitfalls, you can confidently apply these logging techniques to solve practical, real-world problems.

Logging application events to files

By configuring the logging module to write to a file, you create a persistent record of application events that you can analyze long after the program has stopped running.

import logging

# Configure logging to write to a file
logging.basicConfig(
filename='app.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)

# Log application events
logging.info("Application started")
user = "john_doe"
logging.info(f"User {user} logged in")
try:
result = 10 / 0
except Exception as e:
logging.error(f"Error occurred: {e}")
logging.info("Application finished")

This example configures Python’s logging module to direct all output to a file named app.log. The basicConfig() function sets this up, using the format argument to give each log entry a consistent structure with a timestamp and severity level. This makes the log file easy to read and parse.

  • The code uses logging.info() to record standard operational events, such as the application starting and a user logging in.
  • It captures a runtime failure using a try...except block, where logging.error() documents the specific exception.

Creating a simple data visualization in the terminal

Using carefully formatted print() statements, you can turn raw data into a simple text-based histogram, giving you a quick way to visualize information directly in the terminal.

def create_histogram(data, label_width=10):
max_value = max(data.values())
scale_factor = 40 / max_value if max_value > 0 else 1

print(f"{'Category':<{label_width}} | {'Count':<6} | {'Histogram'}")
print("-" * (label_width + 60))

for category, count in data.items():
bar_length = int(count * scale_factor)
bar = "#" * bar_length
print(f"{category:<{label_width}} | {count:<6} | {bar}")

# Sample data: Programming language usage
language_data = {
"Python": 35,
"JavaScript": 30,
"Java": 25,
"C++": 20,
"Go": 15
}

create_histogram(language_data)

The create_histogram function cleverly turns dictionary data into a text-based bar chart. It first finds the largest value in your dataset to calculate a scale_factor. This is the key to making sure the visual bars are scaled proportionally, so they fit neatly within the terminal's width.

  • For each item, it multiplies the count by the scale_factor to determine the length of the bar, which is then built using # characters.
  • Finally, it uses f-strings to align the category, count, and bar into clean columns, making the output easy to read.

Get started with Replit

Put these logging techniques into practice with Replit Agent. Describe a tool like, “a script that processes a large file and shows a tqdm progress bar,” or “a server monitor that uses rich for color-coded logs.”

Replit Agent writes the code, tests for errors, and deploys your application for you. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.