Print Statements
Concepts covered: f-strings
print takes any number of arguments, converts each one to text with str(), joins them with a separator and writes the result to standard output followed by an end marker. The separator defaults to a single space and the end marker to a newline, and both are keyword arguments: sep="|" produces a pipe-delimited line, and end="" keeps the cursor on the same line for the next call. Standard output is a stream, so in a scheduled job everything print writes lands in the task log rather than on a screen, and a print() with no arguments writes a bare newline.
f-strings
An f-string is a string literal with an f before the opening quote, inside which any expression in curly braces is evaluated at runtime and its result spliced into the text. f"user {user_id}" substitutes the value; f"{subtotal_cents / 100}" runs the division first. A colon inside the braces starts a format spec, a small language that controls how the value is rendered: :.2f fixes 2 decimal places, :, inserts thousands separators, and :>10 right-aligns the value in a 10-character column.
user_id = 8814
event = "checkout"
subtotal_cents = 14997
print("user", user_id, event)
print("user", user_id, event, sep="|")
print("subtotal:", end=" ")
print(subtotal_cents)
print(f"user {user_id} spent ${subtotal_cents / 100:.2f} on {event}")
print(f"{subtotal_cents * 3:,} cents across 3 orders")Output:
user 8814 checkout user|8814|checkout subtotal: 14997 user 8814 spent $149.97 on checkout 44,991 cents across 3 orders
The second line shows the same 3 values delimited with |, which is how a quick export to a delimited file begins. The third and fourth calls together produce a single line, because the first of them ended with a space instead of a newline. The f-string divides inside the braces and renders the result with 2 decimals, so the cents integer reads as dollars with no extra variable. The last line applies :, to an integer expression computed inside the braces, and 44991 comes out as 44,991.
The spec sits after the colon and reads in a fixed order: fill and alignment, then width, then the comma, then precision, then the type letter. f"{amount:>12,.2f}" right-aligns a number with thousands separators and 2 decimals in 12 characters, which is how a report column lines up. A spec that rounds for display changes nothing in the value: f"{149.97:.0f}" shows 150 while the stored number stays 149.97, which is the kind of mismatch that sends an analyst hunting for a 3-cent discrepancy between a report and the table underneath it.
sep is applied between arguments and end after the last one. An empty sep glues the values together, so user8814checkout cannot be split apart again; the newline end is the default and leaves the subtotal on a line of its own. The pipe rarely appears in ids or event names, which is why exports use it as a delimiter, though a field that contains one still breaks the split.
The = specifier for debugging
An = after the expression inside the braces, added in Python 3.8, prints the expression's source text with an equals sign after it, then the value's repr. The repr is the point: it keeps the quotes on a string, so a value that is still text cannot pass for a number. It also combines with a format spec, and f"{subtotal_cents / 100=:.2f}" prints subtotal_cents / 100=149.97.
raw_quantity = "3"
quantity = 3
print(raw_quantity, quantity)
print(f"{raw_quantity=} {quantity=}")Output:
3 3 raw_quantity='3' quantity=3
The plain print shows 3 3, and nothing on that line separates the text from the integer. The = form shows the quotes on '3', which is the clue that would have caught the text quantity before it reached a table. In a nightly loader, a line such as print(f"{row_count=} {rejected_rows=}") after each stage leaves a log where every number is printed next to its name, which is faster to read during an incident than a row of bare integers.
About this lesson
This section is part of the Python Foundations: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.