Imagine waking up to a desktop wallpaper that perfectly captures the mood of today's weather—rain-soaked Tokyo streets when it's drizzling, sun-drenched California beaches on clear days, or cozy autumn scenes when leaves are falling. This isn't just a pipe dream; it's a creative application of generative AI that goes beyond chatbots and text generation.
In this Python tutorial, we'll build an automated system that:
- Fetches real-time weather data based on your location
- Generates AI wallpapers using Stable Diffusion Ultra API
- Schedules hourly updates with proper timezone handling
- Organizes wallpapers into collections based on prompts
- Runs as a background service on your computer
Whether you're learning Python automation, exploring generative AI applications, or just want a more dynamic desktop experience, this project demonstrates practical AI integration in everyday tools.
Why Weather-Responsive Wallpapers?
Most generative AI projects focus on chatbots, content generation, or image editing tools. But one of the most exciting aspects of AI is its ability to create ambient, context-aware experiences that adapt to your environment.
Weather-responsive wallpapers offer:
- Mood enhancement: Your desktop reflects the current atmosphere
- Creative variety: Never see the same wallpaper twice
- Location awareness: Prompts can incorporate local landmarks and aesthetics
- Automation practice: Learn scheduling, API integration, and file management
This project showcases Python's strength in automation and API integration while producing tangible, beautiful results every hour.
Tech Stack
This project uses:
- Python 3.10+: Core language for automation logic
- Poetry: Dependency management and virtual environments
- Stable Diffusion Ultra API: AI image generation (migration from legacy SDK)
- Weather API: Real-time weather data (OpenWeatherMap or similar)
- Schedule library: Cron-like job scheduling for Python
- Pytz: Timezone-aware datetime handling
System Architecture
The system consists of four main components:
┌─────────────────┐
│ Weather API │
│ (Location) │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Prompt Engine │─────▶│ Stable Diffusion│
│ (Generator) │ │ Ultra API │
└────────┬────────┘ └────────┬─────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Scheduler │ │ File Manager │
│ (Hourly Runs) │ │ (Organization) │
└─────────────────┘ └──────────────────┘
Data Flow
- Scheduler triggers every hour (timezone-aware)
- Weather API fetches current conditions for your location
- Prompt Engine generates context-aware prompts based on weather + location
- Stable Diffusion Ultra API creates the wallpaper image
- File Manager saves to organized directories and sets as desktop background
Project Setup
Initialize with Poetry
# Create project directory
mkdir weather-wallpapers && cd weather-wallpapers
# Initialize Poetry project
poetry init
# Add dependencies
poetry add stability-sdk requests schedule pytz pillow
poetry add --dev black pytest
# Activate virtual environment
poetry shell
Environment Configuration
Create a .env file for API credentials:
# .env
STABILITY_API_KEY=your_stability_api_key_here
WEATHER_API_KEY=your_openweather_api_key_here
LOCATION_LAT=37.7749
LOCATION_LON=-122.4194
TIMEZONE=America/Los_Angeles
Weather API Integration
First, let's fetch weather data:
# src/weather.py
import os
import requests
from dataclasses import dataclass
from typing import Optional
@dataclass
class WeatherData:
condition: str # "Clear", "Rain", "Clouds", "Snow"
temperature: float
description: str
location: str
class WeatherClient:
def __init__(self):
self.api_key = os.getenv("WEATHER_API_KEY")
self.lat = os.getenv("LOCATION_LAT")
self.lon = os.getenv("LOCATION_LON")
self.base_url = "https://api.openweathermap.org/data/2.5/weather"
def get_current_weather(self) -> Optional[WeatherData]:
"""Fetch current weather for configured location"""
try:
params = {
"lat": self.lat,
"lon": self.lon,
"appid": self.api_key,
"units": "metric"
}
response = requests.get(self.base_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
return WeatherData(
condition=data["weather"][0]["main"],
temperature=data["main"]["temp"],
description=data["weather"][0]["description"],
location=data["name"]
)
except requests.RequestException as e:
print(f"Weather API error: {e}")
return None
Custom Prompt Engineering
The magic happens in prompt generation. We map weather conditions to visual styles:
# src/prompts.py
import random
from src.weather import WeatherData
class PromptGenerator:
# Weather-to-style mappings
WEATHER_STYLES = {
"Clear": [
"golden hour lighting",
"bright sunny day",
"vibrant colors",
"warm atmosphere"
],
"Rain": [
"rain-soaked streets",
"moody atmosphere",
"reflections in puddles",
"dramatic clouds"
],
"Clouds": [
"overcast sky",
"soft diffused lighting",
"muted colors",
"peaceful atmosphere"
],
"Snow": [
"snow-covered landscape",
"winter wonderland",
"crisp cold atmosphere",
"frost and ice"
]
}
# Location-specific aesthetics
LOCATION_STYLES = {
"Tokyo": "Japanese aesthetic, neon lights, urban architecture",
"San Francisco": "Golden Gate Bridge, Victorian houses, foggy hills",
"London": "Big Ben, red telephone boxes, rainy streets",
"Paris": "Eiffel Tower, cobblestone streets, cafe culture",
# Default for unknown locations
"default": "beautiful landscape, natural scenery"
}
def generate_prompt(self, weather: WeatherData, location_hint: str = None) -> str:
"""
Generate a Stable Diffusion prompt based on weather and location
"""
# Base weather style
weather_styles = self.WEATHER_STYLES.get(
weather.condition,
["beautiful landscape"]
)
weather_style = random.choice(weather_styles)
# Location style
location_style = self.LOCATION_STYLES.get(
location_hint or weather.location,
self.LOCATION_STYLES["default"]
)
# Temperature-based modifiers
temp_modifier = self._get_temperature_modifier(weather.temperature)
# Construct final prompt
prompt = f"""
A stunning wallpaper showing {location_style},
{weather_style}, {temp_modifier},
highly detailed, professional photography,
4k resolution, cinematic composition,
{weather.description}
""".strip()
# Clean up extra whitespace
prompt = " ".join(prompt.split())
return prompt
def _get_temperature_modifier(self, temp: float) -> str:
"""Add temperature-based atmospheric modifiers"""
if temp < 0:
return "freezing cold, frost visible"
elif temp < 10:
return "cool and crisp"
elif temp < 20:
return "mild and comfortable"
elif temp < 30:
return "warm and inviting"
else:
return "hot and vibrant"
Scheduling with Timezone Awareness
Important: When scheduling, use minutes or hours—not seconds! Running every few seconds will quickly exhaust your API quota.
# src/scheduler.py
import schedule
import time
import pytz
from datetime import datetime
from src.weather import WeatherClient
from src.prompts import PromptGenerator
from src.generator import WallpaperGenerator
class WallpaperScheduler:
def __init__(self, timezone_str: str = "UTC"):
self.timezone = pytz.timezone(timezone_str)
self.weather_client = WeatherClient()
self.prompt_generator = PromptGenerator()
self.wallpaper_generator = WallpaperGenerator()
def generate_wallpaper_job(self):
"""Main job that runs on schedule"""
print(f"\\n🎨 Starting wallpaper generation...")
print(f"⏰ Local time: {datetime.now(self.timezone)}")
# Fetch weather
weather = self.weather_client.get_current_weather()
if not weather:
print("❌ Could not fetch weather data")
return
print(f"🌤️ Weather: {weather.condition} ({weather.description})")
print(f"🌡️ Temperature: {weather.temperature}°C")
# Generate prompt
prompt = self.prompt_generator.generate_prompt(weather)
negative_prompt = self.prompt_generator.get_negative_prompt()
print(f"📝 Prompt: {prompt[:100]}...")
# Generate wallpaper
filepath = self.wallpaper_generator.generate(
prompt=prompt,
negative_prompt=negative_prompt,
weather_condition=weather.condition
)
if filepath:
# Optionally set as desktop wallpaper
self._set_desktop_wallpaper(filepath)
def start(self, interval_minutes: int = 60):
"""
Start the scheduler
"""
print(f"🚀 Starting wallpaper scheduler (every {interval_minutes} minutes)")
print(f"📍 Timezone: {self.timezone}")
# Generate one immediately on start
self.generate_wallpaper_job()
# Schedule regular updates
schedule.every(interval_minutes).minutes.do(self.generate_wallpaper_job)
# Run scheduler loop
while True:
schedule.run_pending()
time.sleep(1)
Practical Tips & Lessons Learned
1. Cadence Tuning
Don't: Run every few seconds
schedule.every(10).seconds.do(job) # ❌ API quota nightmare!
Do: Run hourly or every few hours
schedule.every(60).minutes.do(job) # ✅ Reasonable cadence
Wallpapers don't need real-time updates. Hourly is perfect—frequent enough to stay current, rare enough to avoid rate limits.
2. Random Seed Management
For variety, use truly random seeds:
import random
seed = random.randint(0, 4294967295) # Full uint32 range
This ensures you never generate the exact same image twice.
3. API Migration Notes
Old SDK (deprecated):
from stability_sdk import client # ❌ Old way
New Ultra API (current):
requests.post("https://api.stability.ai/v2beta/stable-image/generate/ultra") # ✅
The Ultra API is faster, produces better results, and has clearer documentation.
Customization Ideas
Country-Specific Styles
Add more location styles to match your favorite places:
LOCATION_STYLES = {
"Kyoto": "Traditional Japanese architecture, cherry blossoms, zen gardens",
"Iceland": "Northern lights, glaciers, volcanic landscape",
"Dubai": "Modern architecture, desert, luxury",
}
Time-of-Day Variations
Enhance prompts with time awareness:
def add_time_modifier(self, current_hour: int) -> str:
if 5 <= current_hour < 8:
return "sunrise, golden hour, dawn light"
elif 8 <= current_hour < 17:
return "daytime, bright natural light"
elif 17 <= current_hour < 20:
return "sunset, orange sky, dusk"
else:
return "nighttime, moonlight, stars"
Conclusion
We've built a complete automated system that generates AI wallpapers responsive to your current weather. This Python project demonstrates:
- Practical API integration with weather and AI image generation services
- Robust scheduling with timezone awareness and error handling
- Creative prompt engineering that produces varied, contextual results
- Production deployment as a background service
The combination of Weather APIs, Stable Diffusion, and Python automation creates an ambient computing experience that adapts to your environment. Your desktop becomes a living canvas that reflects the world outside.
Beyond wallpapers, this architecture applies to many automation scenarios:
- Context-aware notifications
- Dynamic UI theming
- Location-based content generation
- Scheduled AI operations
If you enjoyed this tutorial, check out more Python automation projects exploring AI integration, API orchestration, and practical ML applications.