Of course! Creating reports in Python is a very common task, especially in data analysis and business intelligence. The best method depends on the complexity of your report, the audience, and where it needs to be delivered.

Here’s a comprehensive guide covering the most popular and effective ways to create reports in Python, from simple scripts to interactive dashboards.
Summary of Approaches
| Method | Best For | Key Libraries | Pros | Cons |
|---|---|---|---|---|
| Simple Scripts | Quick, automated, text-based reports. | print, logging, f-strings |
Easy, no external dependencies. | Not visually appealing, static. |
| Static Reports (PDF/HTML) | Professional, shareable documents. | Jupyter Notebook, Matplotlib, Seaborn, Pandas |
Rich formatting, charts, tables. | Not interactive, requires manual refresh. |
| Dynamic Web Apps | Interactive, exploratory dashboards. | Dash (by Plotly), Streamlit |
Highly interactive, user-friendly. | Requires a server, more complex setup. |
| Templated Reports | Replacing values in pre-made templates. | Jinja2, docx (for Word) |
Full design control, separates logic from design. | Requires creating and managing templates. |
Approach 1: Simple Script-Based Reports
This is the most basic approach, suitable for logging, command-line outputs, or simple emails.
Use Case: A daily summary script that prints key metrics to the console or logs them to a file.
import logging
from datetime import datetime
# --- 1. Data Preparation (Simulated) ---
sales_data = {
'date': datetime.now().strftime('%Y-%m-%d'),
'total_sales': 15420.50,
'new_customers': 42,
'website_visits': 1250
}
# --- 2. Report Generation ---
# Option A: Simple Print
print("--- Daily Sales Report ---")
print(f"Date: {sales_data['date']}")
print(f"Total Sales: ${sales_data['total_sales']:,.2f}")
print(f"New Customers: {sales_data['new_customers']}")
print(f"Website Visits: {sales_data['website_visits']}")
print("-------------------------\n")
# Option B: Using Logging (Better for automation)
logging.basicConfig(
filename='sales_report.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logging.info("--- Daily Sales Report ---")
logging.info(f"Date: {sales_data['date']}")
logging.info(f"Total Sales: ${sales_data['total_sales']:,.2f}")
logging.info(f"New Customers: {sales_data['new_customers']}")
logging.info(f"Website Visits: {sales_data['website_visits']}")
logging.info("-------------------------")
print("Report has been logged to sales_report.log")
Approach 2: Static Reports (PDF & HTML) with Jupyter Notebooks
This is a very popular method for data analysts. You can create a beautifully formatted report with text, code, charts, and tables directly in a notebook and then export it.

Use Case: A monthly performance report for management that includes charts and tables.
Libraries:
pandas: For data manipulation.matplotlib&seaborn: For plotting.jupyter: The environment itself.
Steps:
- Create a Jupyter Notebook (
.ipynbfile). - Write your analysis code in cells.
- Use Markdown cells for titles, explanations, and formatting.
- Export the final notebook as an HTML or PDF file.
Example Notebook Structure:

# Monthly Sales Performance Report
## Executive Summary
Total sales for October showed a 15% increase compared to last month. The "Electronics" category was the top performer.
## Data Analysis
```python
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# Load data
df = pd.read_csv('sales_data.csv')
# --- Data Manipulation ---
df['date'] = pd.to_datetime(df['date'])
monthly_sales = df.groupby(df['date'].dt.to_period('M'))['sales'].sum().reset_index()
monthly_sales['date'] = monthly_sales['date'].dt.strftime('%Y-%m')
# --- Visualization ---
plt.style.use('seaborn-v0_8-whitegrid')
fig, ax = plt.subplots(figsize=(10, 6))
sns.barplot(data=monthly_sales, x='date', y='sales', ax=ax, palette='viridis')
ax.set_title('Monthly Sales Trend', fontsize=16)
ax.set_xlabel('Month')
ax.set_ylabel('Total Sales ($)')
plt.xticks(rotation=45)
plt.tight_layout()
# Display the plot in the notebook
plt.show()
# Display a table of top products
top_products = df.groupby('product_name')['sales'].sum().sort_values(ascending=False).head(5)
print("Top 5 Products by Sales:")
print(top_products.to_frame())
Conclusion
We recommend increasing the marketing budget for the Electronics category for November.
**How to Export:**
* **HTML:** `File` -> `Download as` -> `HTML (.html)`
* **PDF:** `File` -> `Download as` -> `PDF via LaTeX` (requires a LaTeX installation like MiKTeX on Windows or MacTeX on macOS).
---
### Approach 3: Dynamic Web Apps with Dash or Streamlit
For interactive reports where the user can filter, zoom, and explore the data themselves. This is the modern standard for business intelligence.
#### Example with Dash (by Plotly)
Dash is powerful and highly customizable, great for complex applications.
**Use Case:** An interactive dashboard where a user can select a product category and see the sales trend over time.
**Installation:**
`pip install dash pandas plotly`
**Code (`app.py`):**
```python
import dash
from dash import dcc, html, Input, Output
import plotly.express as px
import pandas as pd
# Assume this data is loaded from a database or file
df = pd.read_csv('sales_data.csv')
df['date'] = pd.to_datetime(df['date'])
# Get unique list of categories for the dropdown
categories = df['category'].unique()
# Initialize the Dash app
app = dash.Dash(__name__)
# Define the app layout
app.layout = html.Div([
html.H1("Interactive Sales Dashboard", style={'textAlign': 'center'}),
# Dropdown for category selection
html.Div([
dcc.Dropdown(
id='category-dropdown',
options=[{'label': cat, 'value': cat} for cat in categories],
value=categories[0], # Default value
clearable=False
)
], style={'width': '50%', 'margin': 'auto'}),
# Graph component to display the chart
dcc.Graph(id='sales-graph')
])
# Define the callback to update the graph based on dropdown selection
@app.callback(
Output('sales-graph', 'figure'),
Input('category-dropdown', 'value')
)
def update_graph(selected_category):
# Filter data based on selection
filtered_df = df[df['category'] == selected_category]
# Aggregate sales by day
daily_sales = filtered_df.groupby('date')['sales'].sum().reset_index()
# Create the plot
fig = px.line(daily_sales, x='date', y='sales',
title=f'Daily Sales for {selected_category}',
labels={'sales': 'Total Sales ($)', 'date': 'Date'})
return fig
# Run the app
if __name__ == '__main__':
app.run_server(debug=True)
Run the script (python app.py) and open http://127.0.0.1:8050 in your browser.
Example with Streamlit
Streamlit is even simpler to get started with, perfect for quick prototypes.
Installation:
pip install streamlit pandas plotly
Code (app.py):
import streamlit as st
import pandas as pd
import plotly.express as px
# Load data
df = pd.read_csv('sales_data.csv')
df['date'] = pd.to_datetime(df['date'])
# --- Streamlit App UI ---
st.set_page_config(layout="wide")"Interactive Sales Dashboard")
# Create a sidebar for controls
st.sidebar.header("Filters")
selected_category = st.sidebar.selectbox(
"Select a Category",
options=df['category'].unique()
)
# Filter the data based on selection
filtered_df = df[df['category'] == selected_category]
# --- Display Data ---
st.subheader(f"Sales Data for {selected_category}")
st.dataframe(filtered_df)
# --- Display a Chart ---
st.subheader("Sales Trend Chart")
daily_sales = filtered_df.groupby('date')['sales'].sum().reset_index()
fig = px.line(daily_sales, x='date', y='sales', title='Daily Sales Trend')
st.plotly_chart(fig, use_container_width=True)
st.write("This dashboard updates automatically as you change the filter in the sidebar.")
Run the script (streamlit run app.py) and open the provided URL.
Approach 4: Templated Reports (e.g., Word or HTML)
This approach is best when you need to generate a document with a very specific layout, like a contract or a formal report, and just need to insert data into placeholders.
Use Case: Generating personalized "Thank You" letters for customers.
Library: Jinja2 for HTML/Text templates.
Create a Template File (letter_template.html):
<!DOCTYPE html>
<html>
<head>Thank You Letter</title>
</head>
<body>
<h1>Dear {{ customer_name }},</h1>
<p>
Thank you for your recent purchase of {{ product_name }} on {{ purchase_date }}.
We hope you are enjoying it!
</p>
<p>
Your order number is {{ order_number }}. If you have any questions, please don't hesitate to contact us.
</p>
<p>Sincerely,<br>The Team at {{ company_name }}</p>
</body>
</html>
Create the Python Script (generate_letter.py):
from jinja2 import Environment, FileSystemLoader
from datetime import datetime
# --- Data ---
customer_data = {
'customer_name': 'Alice Smith',
'product_name': 'SuperWidget Pro',
'purchase_date': datetime.now().strftime('%B %d, %Y'),
'order_number': '98765',
'company_name': 'Awesome Widgets Inc.'
}
# --- Setup Jinja2 Environment ---
# This tells Jinja2 where to find the template files
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('letter_template.html')
# --- Render the Template ---
# This substitutes the placeholders with actual data
output = template.render(customer_data)
# --- Save the Output to a File ---
with open('letter_for_alice.html', 'w') as f:
f.write(output)
print("Letter generated successfully: letter_for_alice.html")
Which One Should You Choose?
- For yourself or a quick log: Use Approach 1.
- For a polished, shareable PDF/HTML document: Use Approach 2 (Jupyter Notebook).
- For an interactive dashboard that users will explore: Use Approach 3 (Dash or Streamlit). Start with Streamlit for simplicity.
- For filling in a pre-designed document: Use Approach 4 (Jinja2).
