Session Overview
Welcome to our exploration of Python's input and output operations! Today, we'll learn how Python programs can interact with users through the console, read from and write to files, and format data for presentation. These fundamental skills will enable you to create interactive programs, process data from external sources, and present information in a meaningful way.
Console Input and Output
Basic Output with print()
The print() function is the most common way to display output in Python:
# Basic printing
print("Hello, World!") # Displays: Hello, World!
# Printing multiple items
print("The answer is", 42) # Displays: The answer is 42
# Using variables
name = "Alice"
age = 30
print(name, "is", age, "years old") # Displays: Alice is 30 years old
The print() function has several useful parameters:
# Customizing separators between items
print("apple", "banana", "cherry", sep=", ") # Displays: apple, banana, cherry
# Customizing end character (default is newline)
print("Hello", end=" ")
print("World!") # Displays: Hello World!
# Redirecting output to a file
with open("output.txt", "w") as f:
print("This goes to the file", file=f)
# Handling non-string objects
print([1, 2, 3]) # Displays: [1, 2, 3]
print({"name": "Alice", "age": 30}) # Displays: {'name': 'Alice', 'age': 30}
Basic Input with input()
The input() function allows users to enter data from the keyboard:
# Basic input
name = input("Enter your name: ")
print("Hello,", name)
# Note: input() always returns a string!
age_str = input("Enter your age: ")
age = int(age_str) # Convert string to integer
print("Next year, you will be", age + 1)
# Combining input and conversion in one step
height = float(input("Enter your height in meters: "))
print("Your height in centimeters is", height * 100)
# Simple yes/no input
response = input("Do you like Python? (yes/no): ").lower()
if response == "yes":
print("Great choice!")
else:
print("You might change your mind!")
Analogy: Console I/O as a Conversation
Think of console input and output as a conversation between your program and the user:
print()is like your program speaking to the userinput()is like your program listening to the user- Just as in a conversation, the program needs to clearly communicate what input it expects
- And like understanding speech in different languages, the program needs to convert the input to the right type
Good programs, like good conversationalists, provide clear prompts, listen carefully to responses, and give meaningful feedback.
Formatting Output
Python offers several ways to format output for better presentation:
String Concatenation
# Simple concatenation with + (only works with strings)
name = "Alice"
greeting = "Hello, " + name + "!"
print(greeting) # Displays: Hello, Alice!
# Need to convert non-strings to strings first
age = 30
message = name + " is " + str(age) + " years old."
print(message) # Displays: Alice is 30 years old.
F-strings (Python 3.6+)
F-strings provide a concise and readable way to embed expressions in string literals:
# Basic f-string
name = "Alice"
age = 30
print(f"{name} is {age} years old.") # Displays: Alice is 30 years old.
# Expressions in f-strings
print(f"{name} will be {age + 10} years old in 10 years.")
# Formatting numbers
pi = 3.14159265359
print(f"Pi to 2 decimal places: {pi:.2f}") # Displays: Pi to 2 decimal places: 3.14
# Width and alignment
for i in range(1, 6):
print(f"{i:2d} {i*i:3d} {i*i*i:4d}")
# Displays:
# 1 1 1
# 2 4 8
# 3 9 27
# 4 16 64
# 5 25 125
# Named placeholders with dictionaries
person = {"name": "Alice", "age": 30}
print(f"{person['name']} is {person['age']} years old.")
str.format() Method
The format() method is another way to format strings:
# Basic formatting
name = "Alice"
age = 30
print("{} is {} years old.".format(name, age))
# Positional arguments
print("{0} is {1} years old. {0} lives in New York.".format(name, age))
# Named arguments
print("{name} is {age} years old.".format(name=name, age=age))
# Reusing the person dictionary
print("{name} is {age} years old.".format(**person)) # Unpacking dictionary
# Number formatting
print("Pi to 3 decimal places: {:.3f}".format(3.14159)) # Displays: Pi to 3 decimal places: 3.142
% Operator (Older Style)
The % operator is an older way to format strings, still found in legacy code:
# Basic formatting
name = "Alice"
age = 30
print("%s is %d years old." % (name, age))
# Named placeholders
print("%(name)s is %(age)d years old." % {"name": name, "age": age})
# Number formatting
print("Pi to 4 decimal places: %.4f" % 3.14159) # Displays: Pi to 4 decimal places: 3.1416
Format Specifiers
Format specifiers allow precise control over how values are displayed:
# Common format specifiers (work with both f-strings and str.format())
# Width and alignment
for name in ["Alice", "Bob", "Charlie"]:
print(f"{name:10}") # Right-aligned in 10-character field
# Left, right, and center alignment
print(f"{'left':10}") # Left-aligned (default for strings)
print(f"{'right':>10}") # Right-aligned
print(f"{'center':^10}") # Center-aligned
# Fill character
print(f"{'test':*^10}") # '*****test*****'
# Number formatting
print(f"{123:05d}") # '00123' (zero-padded)
print(f"{123:+d}") # '+123' (show sign)
print(f"{-123:+d}") # '-123'
print(f"{-123: d}") # '-123' (space for positive numbers)
print(f"{123: d}") # ' 123'
# Float formatting
print(f"{3.14159:.2f}") # '3.14' (2 decimal places)
print(f"{3.14159:+.2f}") # '+3.14' (with sign)
print(f"{3.14159:06.2f}") # '003.14' (zero-padded, 6 total width)
# Percentage
print(f"{0.25:.1%}") # '25.0%' (as percentage)
# Scientific notation
print(f"{1000000:.2e}") # '1.00e+06'
# Binary, octal, hex
print(f"{42:b}") # '101010' (binary)
print(f"{42:o}") # '52' (octal)
print(f"{42:x}") # '2a' (hex, lowercase)
print(f"{42:X}") # '2A' (hex, uppercase)
print(f"{42:#x}") # '0x2a' (hex with prefix)
File Input and Output Basics
Python makes it easy to read from and write to files:
Opening and Closing Files
# Opening a file (creates it if it doesn't exist)
file = open("example.txt", "w") # 'w' for write mode
file.write("Hello, File I/O!")
file.close() # Always close files when done
# Better approach using 'with' statement (automatically closes file)
with open("example.txt", "w") as file:
file.write("Hello, File I/O using 'with'!")
# File automatically closed when the block exits
Common file modes include:
"r"- Read (default)"w"- Write (creates file, truncates if exists)"a"- Append"r+"- Read and write"b"- Binary mode (e.g.,"rb"for reading binary)"t"- Text mode (default)
Writing to Files
# Write strings to a file
with open("fruits.txt", "w") as file:
file.write("apple\n") # \n for newline
file.write("banana\n")
file.write("cherry\n")
# Using writelines() for multiple lines
fruits = ["apple\n", "banana\n", "cherry\n"]
with open("fruits2.txt", "w") as file:
file.writelines(fruits)
# Using print() with file parameter
with open("fruits3.txt", "w") as file:
print("apple", file=file)
print("banana", file=file)
print("cherry", file=file) # print() adds newlines automatically
Reading from Files
# Reading entire file at once
with open("fruits.txt", "r") as file:
content = file.read()
print(content)
# Reading line by line
with open("fruits.txt", "r") as file:
line = file.readline()
while line:
print(line, end="") # readline() keeps newline characters
line = file.readline()
# Using readlines() to get a list of lines
with open("fruits.txt", "r") as file:
lines = file.readlines()
print(lines) # ['apple\n', 'banana\n', 'cherry\n']
# Most efficient way: iterating over the file object
with open("fruits.txt", "r") as file:
for line in file:
print(line, end="")
File Positions
# Moving the file pointer
with open("fruits.txt", "r") as file:
first_line = file.readline()
print(first_line)
# Get current position
position = file.tell()
print(f"Current position: {position}")
# Move to beginning
file.seek(0)
# Read first 5 characters
start = file.read(5)
print(start) # "apple"
Analogy: Files as Notebooks
Think of files as notebooks:
- Opening a file is like taking a notebook off a shelf
- Writing to a file is like writing in the notebook
- Reading from a file is like reading what's in the notebook
- The file pointer is like your finger keeping your place as you read
- Closing the file is like putting the notebook back on the shelf
- The 'with' statement is like having an assistant who always puts the notebook back for you
Just as you would close a notebook when done to keep it safe, properly closing files ensures data integrity and resource management.
Advanced File Operations
Working with Binary Files
# Writing binary data
with open("binary_file.bin", "wb") as file:
file.write(b"Binary data: \x00\x01\x02\x03")
# Reading binary data
with open("binary_file.bin", "rb") as file:
binary_data = file.read()
print(binary_data) # b'Binary data: \x00\x01\x02\x03'
# Converting to bytes
byte_array = bytearray(binary_data)
print(byte_array) # bytearray(b'Binary data: \x00\x01\x02\x03')
Working with CSV Files
CSV (Comma-Separated Values) is a common format for tabular data:
import csv
# Writing CSV data
with open("people.csv", "w", newline="") as file:
writer = csv.writer(file)
# Write header row
writer.writerow(["Name", "Age", "City"])
# Write data rows
writer.writerow(["Alice", 30, "New York"])
writer.writerow(["Bob", 25, "Los Angeles"])
writer.writerow(["Charlie", 35, "Chicago"])
# Reading CSV data
with open("people.csv", "r", newline="") as file:
reader = csv.reader(file)
# Skip header
header = next(reader)
print(f"Header: {header}")
# Process data rows
for row in reader:
print(f"{row[0]} is {row[1]} years old and lives in {row[2]}")
# Using dictionaries with CSV
with open("people_dict.csv", "w", newline="") as file:
fieldnames = ["Name", "Age", "City"]
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"Name": "Alice", "Age": 30, "City": "New York"})
writer.writerow({"Name": "Bob", "Age": 25, "City": "Los Angeles"})
# Reading CSV as dictionaries
with open("people_dict.csv", "r", newline="") as file:
reader = csv.DictReader(file)
for row in reader:
print(f"{row['Name']} is {row['Age']} years old and lives in {row['City']}")
Working with JSON Files
JSON (JavaScript Object Notation) is a popular format for structured data:
import json
# Creating Python data
data = {
"people": [
{"name": "Alice", "age": 30, "city": "New York", "active": True},
{"name": "Bob", "age": 25, "city": "Los Angeles", "active": False},
{"name": "Charlie", "age": 35, "city": "Chicago", "active": True}
],
"organization": "Example Corp",
"founded": 2010
}
# Writing JSON to a file
with open("data.json", "w") as file:
json.dump(data, file, indent=4) # indent for pretty formatting
# Reading JSON from a file
with open("data.json", "r") as file:
loaded_data = json.load(file)
print(loaded_data["organization"])
for person in loaded_data["people"]:
print(f"{person['name']} is {person['age']} years old")
# Converting to/from JSON strings
json_string = json.dumps(data, indent=2)
print(json_string)
parsed_data = json.loads(json_string)
print(parsed_data["founded"])
Error Handling in I/O Operations
I/O operations can fail for various reasons. It's important to handle these errors gracefully:
Handling File I/O Errors
# Basic try-except for file operations
try:
with open("nonexistent_file.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("The file does not exist!")
except PermissionError:
print("You don't have permission to access this file!")
except Exception as e:
print(f"An error occurred: {e}")
# Handling multiple files
def safely_read_file(filename):
try:
with open(filename, "r") as file:
return file.read()
except FileNotFoundError:
print(f"Warning: {filename} not found, skipping.")
return None
# Process multiple files, continuing even if some fail
files = ["file1.txt", "nonexistent.txt", "file2.txt"]
contents = {}
for filename in files:
content = safely_read_file(filename)
if content:
contents[filename] = content
Handling User Input Errors
# Robust user input with validation
def get_integer_input(prompt):
"""Get an integer input from the user, with validation."""
while True:
try:
value = int(input(prompt))
return value
except ValueError:
print("Invalid input. Please enter a valid integer.")
def get_float_input(prompt):
"""Get a float input from the user, with validation."""
while True:
try:
value = float(input(prompt))
return value
except ValueError:
print("Invalid input. Please enter a valid number.")
# Example usage
age = get_integer_input("Enter your age: ")
height = get_float_input("Enter your height in meters: ")
Context Managers for Resource Management
Context managers (using the with statement) help ensure resources are properly managed:
Using Built-in Context Managers
# File as context manager
with open("example.txt", "w") as file:
file.write("Using context manager")
# File automatically closed, even if an exception occurs
# Multiple context managers
with open("input.txt", "r") as infile, open("output.txt", "w") as outfile:
content = infile.read()
outfile.write(content.upper())
Creating Custom Context Managers
class Timer:
"""A context manager for timing code execution."""
def __enter__(self):
import time
self.start_time = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
import time
self.end_time = time.time()
self.elapsed = self.end_time - self.start_time
print(f"Elapsed time: {self.elapsed:.6f} seconds")
# Return False to let exceptions propagate, True to suppress them
return False
# Using our custom context manager
with Timer():
# Code to time
result = 0
for i in range(1000000):
result += i
print(f"Sum: {result}") # Sum will be displayed, then elapsed time
The contextlib Module
from contextlib import contextmanager
@contextmanager
def file_opener(filename, mode):
"""Simplified file opener context manager."""
try:
f = open(filename, mode)
yield f
finally:
f.close()
# Using our decorator-based context manager
with file_opener("example.txt", "w") as file:
file.write("Using contextlib.contextmanager")
# Creating a do-nothing context manager
@contextmanager
def no_operation():
print("Entering context")
yield
print("Exiting context")
with no_operation():
print("Inside the context block")
Practical Examples
Simple Text Editor
def simple_text_editor():
"""A very simple text editor."""
filename = input("Enter filename to edit: ")
# Try to load existing file
try:
with open(filename, "r") as file:
content = file.read()
print(f"Loaded file: {filename}")
except FileNotFoundError:
content = ""
print(f"New file: {filename}")
# Show current content
print("\nCurrent content:")
print("-" * 40)
print(content)
print("-" * 40)
# Edit content
print("\nEnter new content (type 'EOF' on a new line to finish):")
new_content = []
while True:
line = input()
if line == "EOF":
break
new_content.append(line)
# Save or discard changes
save = input("\nSave changes? (y/n): ").lower()
if save == "y":
with open(filename, "w") as file:
file.write("\n".join(new_content))
print(f"Changes saved to {filename}")
else:
print("Changes discarded")
# Uncomment to run the editor
# simple_text_editor()
CSV Data Processor
import csv
def process_csv_data(input_file, output_file):
"""Read CSV data, process it, and write results to a new CSV file."""
# Read input data
with open(input_file, "r", newline="") as infile:
reader = csv.DictReader(infile)
data = list(reader)
print(f"Read {len(data)} rows from {input_file}")
# Process data (simple example: calculate age in months)
for row in data:
try:
age_years = int(row["Age"])
row["Age_Months"] = age_years * 12
except (ValueError, KeyError):
row["Age_Months"] = "N/A"
# Write output data
with open(output_file, "w", newline="") as outfile:
# Get all field names, including new ones
fieldnames = list(data[0].keys())
writer = csv.DictWriter(outfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(data)
print(f"Processed data written to {output_file}")
# Example usage
# process_csv_data("people.csv", "people_processed.csv")
Log File Analyzer
def analyze_log_file(log_file):
"""A simple log file analyzer that counts error types."""
error_types = {}
try:
with open(log_file, "r") as file:
line_count = 0
error_count = 0
for line in file:
line_count += 1
# Simple example: count lines containing "ERROR"
if "ERROR" in line:
error_count += 1
# Extract error type (simple example)
parts = line.split("ERROR:", 1)
if len(parts) > 1:
error_message = parts[1].strip()
# Get first few words as error type
error_type = " ".join(error_message.split()[:3])
error_types[error_type] = error_types.get(error_type, 0) + 1
# Print summary
print(f"Log File Analysis: {log_file}")
print(f"Total lines: {line_count}")
print(f"Error lines: {error_count} ({error_count/line_count:.1%} of total)")
if error_types:
print("\nError Types:")
for error_type, count in sorted(error_types.items(), key=lambda x: x[1], reverse=True):
print(f"- {error_type}: {count} occurrences")
except FileNotFoundError:
print(f"Error: Log file '{log_file}' not found.")
except Exception as e:
print(f"Error analyzing log file: {e}")
# Example usage (create a sample log file first)
with open("sample.log", "w") as log:
log.write("2025-04-15 12:30:45 INFO: Application started\n")
log.write("2025-04-15 12:31:10 ERROR: Database connection failed\n")
log.write("2025-04-15 12:31:15 INFO: Retrying connection\n")
log.write("2025-04-15 12:32:20 ERROR: Database connection failed\n")
log.write("2025-04-15 12:33:45 ERROR: Invalid user input\n")
log.write("2025-04-15 12:35:12 INFO: User logged in\n")
# analyze_log_file("sample.log")
Best Practices for Input and Output
Console I/O Best Practices
- Clear prompts: Always provide clear, specific instructions when asking for input
- Input validation: Always validate and sanitize user input
- Error messages: Provide helpful error messages when input is incorrect
- Confirmation: Confirm critical actions before proceeding
- Formatting: Use appropriate formatting for different types of output
# Example of good console I/O practices
def get_user_info():
"""Get and validate user information."""
# Clear prompt with expected format
name = input("Enter your name: ")
while not name:
print("Error: Name cannot be empty.")
name = input("Enter your name: ")
# Input validation with helpful error message
while True:
try:
age = int(input("Enter your age (18-120): "))
if 18 <= age <= 120:
break
print("Error: Age must be between 18 and 120.")
except ValueError:
print("Error: Please enter a valid number.")
# Confirmation of input
print("\nPlease confirm your information:")
print(f"Name: {name}")
print(f"Age: {age}")
confirm = input("Is this correct? (y/n): ").lower()
return name, age, confirm == 'y'
# get_user_info()
File I/O Best Practices
- Always use
withstatement: Ensures files are properly closed - Error handling: Use appropriate exception handling for file operations
- Path handling: Use
os.pathorpathlibfor cross-platform path handling - Buffering: Process large files in chunks or line by line
- Backup: Create backups before modifying important files
import os
from pathlib import Path
def safe_file_operations():
"""Example of best practices for file operations."""
# Using pathlib for platform-independent paths
data_dir = Path("data")
input_file = data_dir / "input.txt"
output_file = data_dir / "output.txt"
# Create directory if it doesn't exist
os.makedirs(data_dir, exist_ok=True)
# Checking if file exists before reading
if not input_file.exists():
print(f"Warning: {input_file} does not exist")
return
# Create backup before modifying
if output_file.exists():
backup_file = output_file.with_suffix(".bak")
output_file.rename(backup_file)
print(f"Created backup: {backup_file}")
try:
# Processing large file efficiently
with open(input_file, "r") as infile, open(output_file, "w") as outfile:
for line in infile: # Read line by line, not all at once
# Process line
processed_line = line.upper()
outfile.write(processed_line)
print(f"Processing complete: {input_file} → {output_file}")
except Exception as e:
print(f"Error during file processing: {e}")
# Restore from backup if something went wrong
if 'backup_file' in locals() and backup_file.exists():
backup_file.rename(output_file)
print(f"Restored from backup due to error")
# safe_file_operations()
Practice Exercises
Exercise 1: Enhanced Calculator
Create a calculator program that takes user input for two numbers and an operation, performs the calculation, and displays the result with proper formatting.
Exercise 2: File Copier
Write a program that copies the contents of one file to another, with these features:
- Asks the user for source and destination filenames
- Verifies the source file exists
- Asks for confirmation before overwriting an existing destination file
- Reports success or failure
Exercise 3: CSV Data Analyzer
Create a program that reads a CSV file containing tabular data (e.g., sales records, student scores) and produces a summary report with statistics like averages, totals, min/max values, etc.
Exercise 4: Simple Note-Taking App
Build a simple console-based note-taking application that allows users to:
- Create new notes
- View existing notes
- Search for notes by keyword
- Delete notes
Store the notes in a text or JSON file.
Exercise 5: Log Parser
Create a log parser that reads a log file, extracts important information (e.g., error messages, timestamps), and generates a summary report.
Wrapping Up and Next Steps
Today we've explored the fundamentals of input and output in Python, from basic console interaction to file operations and formatting. These skills form the foundation for creating interactive programs and processing data from external sources.
Key Takeaways
- Console I/O with
input()andprint()provides a simple way to interact with users - Python offers multiple string formatting options, with f-strings being the most modern and readable
- File I/O operations allow programs to read from and write to external files
- Context managers (the
withstatement) ensure proper resource management - Error handling is essential for robust I/O operations
- Specialized modules like
csvandjsonsimplify working with common file formats
Where to Go from Here
- Explore more advanced file formats like XML, YAML, or Excel spreadsheets
- Learn about database I/O using Python's database modules (sqlite3, SQLAlchemy, etc.)
- Investigate network I/O for communicating with web services and APIs
- Dive into GUI programming for more sophisticated user interfaces
- Explore specialized I/O libraries for scientific computing and data analysis
Additional Resources
- Python Documentation: Input and Output
- Python Documentation: input() Function
- Python Documentation: print() Function
- Python Documentation: csv Module
- Python Documentation: json Module
- Python Documentation: pathlib Module
In our next session, we'll explore control flow in Python - how to make decisions, create loops, and control the execution of your programs.