Flask Signals

Back

Loading concept...

Flask Signals: The Secret Messenger System 🚀

Imagine you have a house with many rooms. When the doorbell rings, everyone in the house hears it - they don’t need to watch the door constantly. Flask Signals work exactly like that doorbell!


🎯 What Are Flask Signals?

Think of signals like announcements in a school. When the principal makes an announcement over the speaker, every classroom hears it at the same time. They don’t need to keep asking “Did something happen?”

Flask Signals let different parts of your app “announce” when something happens, and other parts can “listen” and react.

Why Use Signals?

Without Signals 😓 With Signals 😊
Parts of your app constantly check for changes Parts listen and react automatically
Code gets tangled together Code stays clean and separate
Adding new features means changing old code New features just “subscribe”

📻 Built-in Flask Signals

Flask comes with ready-made signals - like pre-installed doorbells! Here are the most important ones:

The Request Family 📨

from flask import request_started
from flask import request_finished
from flask import request_tearing_down

# These fire during every request!

Simple Example:

from flask import Flask
from flask import request_started

app = Flask(__name__)

def log_request(sender, **extra):
    print("A request just started!")

# Connect our function to the signal
request_started.connect(log_request, app)

What Each Built-in Signal Does

graph TD A["User Makes Request"] --> B["request_started"] B --> C["Your App Processes"] C --> D["request_finished"] D --> E["request_tearing_down"] E --> F["Response Sent"] style B fill:#4CAF50,color:white style D fill:#2196F3,color:white style E fill:#FF9800,color:white
Signal When It Fires Real Use
request_started Request begins Log who visited
request_finished Response ready Track timing
request_tearing_down Cleanup time Close connections
got_request_exception Error occurred Send alert
template_rendered Template done Debug templates

🔨 Creating Custom Signals

Sometimes the built-in doorbells aren’t enough. You want your own special announcement system!

Step 1: Import the Signal Maker

from blinker import signal

# Create your custom signal
user_logged_in = signal('user-logged-in')

Step 2: Use Your Signal

Think of it like this:

  • You create a bell named “user-logged-in”
  • Anyone can ring this bell
  • Anyone can listen for this bell
from blinker import signal

# Create the signal (the bell)
order_placed = signal('order-placed')

# Now you can use it anywhere!

Complete Example

from flask import Flask
from blinker import signal

app = Flask(__name__)

# 1. Create custom signal
user_signed_up = signal('user-signed-up')

# 2. This will run when signal fires
def send_welcome_email(sender, **data):
    user = data.get('user')
    print(f"Sending welcome to {user}!")

# 3. Connect listener to signal
user_signed_up.connect(send_welcome_email)

@app.route('/signup')
def signup():
    # 4. Fire the signal!
    user_signed_up.send(app, user="Alice")
    return "Welcome!"

👂 Subscribing to Signals

Subscribing = “I want to hear that announcement!”

Method 1: Using .connect()

from flask import request_started

def my_listener(sender, **extra):
    print("I heard the signal!")

# Subscribe to the signal
request_started.connect(my_listener, app)

Method 2: Using Decorators

from flask import template_rendered

@template_rendered.connect_via(app)
def log_template(sender, template, **extra):
    print(f"Template {template.name} rendered!")

The Key Parts

graph LR A["Signal"] -->|connect| B["Your Function"] B -->|receives| C["sender"] B -->|receives| D["extra data"] style A fill:#E91E63,color:white style B fill:#9C27B0,color:white
Parameter What It Is Example
sender Who sent the signal Your Flask app
**extra Any extra data sent User info, etc.

Subscribing to Specific Senders Only

# Only listen when THIS app sends it
request_started.connect(my_func, app)

# Listen to ALL senders
request_started.connect(my_func)

📤 Sending Signals

Sending = “Ring the bell! Make the announcement!”

Basic Send

from blinker import signal

# Create signal
task_completed = signal('task-completed')

# Send it! (ring the bell)
task_completed.send(app)

Sending With Data

# Send extra information with the signal
task_completed.send(
    app,
    task_name="Download",
    status="success",
    time_taken=5.2
)

Where to Send Signals

from flask import Flask
from blinker import signal

app = Flask(__name__)
payment_received = signal('payment-received')

@app.route('/pay')
def process_payment():
    # ... payment logic ...

    # Send signal with data
    payment_received.send(
        app,
        amount=99.99,
        customer="Bob"
    )

    return "Payment done!"

The Send Pattern

graph TD A["Something Happens"] --> B["Call signal.send"] B --> C["Pass sender"] B --> D["Pass extra data"] C --> E["All Listeners Receive It"] D --> E style B fill:#00BCD4,color:white style E fill:#8BC34A,color:white

🎛️ Signal Handlers

A handler is just a function that runs when a signal fires. Think of handlers as workers who respond to announcements.

Anatomy of a Handler

def my_handler(sender, **kwargs):
    # sender = who sent the signal
    # kwargs = extra data dictionary

    print(f"Got signal from {sender}")
    print(f"Data: {kwargs}")

Real Handler Examples

Example 1: Logging Handler

def log_handler(sender, **kwargs):
    timestamp = kwargs.get('time')
    action = kwargs.get('action')
    print(f"[{timestamp}] {action}")

# Connect it
user_action.connect(log_handler)

Example 2: Email Handler

def email_handler(sender, **kwargs):
    email = kwargs.get('email')
    event = kwargs.get('event')

    if event == 'signup':
        send_email(email, "Welcome!")
    elif event == 'purchase':
        send_email(email, "Thanks!")

purchase_made.connect(email_handler)

Multiple Handlers, One Signal

from blinker import signal

order_placed = signal('order-placed')

# Handler 1: Update inventory
def update_stock(sender, **kw):
    print("Reducing stock...")

# Handler 2: Notify warehouse
def notify_warehouse(sender, **kw):
    print("Alerting warehouse...")

# Handler 3: Send confirmation
def send_confirmation(sender, **kw):
    print("Emailing customer...")

# All three listen to same signal!
order_placed.connect(update_stock)
order_placed.connect(notify_warehouse)
order_placed.connect(send_confirmation)

# When you send...
order_placed.send(app, item="Book", qty=1)
# ALL three handlers run!
graph TD A["order_placed.send"] --> B["update_stock"] A --> C["notify_warehouse"] A --> D["send_confirmation"] style A fill:#FF5722,color:white style B fill:#3F51B5,color:white style C fill:#3F51B5,color:white style D fill:#3F51B5,color:white

🎓 Putting It All Together

Here’s a complete mini-app showing everything:

from flask import Flask
from blinker import signal

app = Flask(__name__)

# 1. CREATE custom signals
user_registered = signal('user-registered')
user_logged_in = signal('user-logged-in')

# 2. HANDLERS (signal workers)
def welcome_email(sender, **kw):
    print(f"Welcome {kw['name']}!")

def log_login(sender, **kw):
    print(f"{kw['name']} logged in")

def give_bonus(sender, **kw):
    print(f"Bonus points for {kw['name']}!")

# 3. SUBSCRIBE handlers to signals
user_registered.connect(welcome_email)
user_registered.connect(give_bonus)
user_logged_in.connect(log_login)

# 4. SEND signals in routes
@app.route('/register/<name>')
def register(name):
    user_registered.send(app, name=name)
    return f"Registered {name}!"

@app.route('/login/<name>')
def login(name):
    user_logged_in.send(app, name=name)
    return f"Hello {name}!"

💡 Quick Tips

Do This ✅ Not This ❌
Keep handlers fast Slow handlers block everything
Pass only needed data Don’t send huge objects
Use clear signal names Vague names cause confusion
Disconnect when done Memory leaks from orphan handlers

Disconnecting Signals

# When you're done listening
my_signal.disconnect(my_handler)

🏆 You Did It!

You now understand Flask Signals:

  1. Built-in signals - Flask’s ready-made announcements
  2. Custom signals - Your own bells to ring
  3. Subscribing - Listening for announcements
  4. Sending - Making announcements
  5. Handlers - Workers who respond

Remember the doorbell analogy: Create a bell, connect listeners, ring when needed. Everyone hears, everyone reacts!

graph LR A["Create Signal"] --> B["Subscribe Handlers"] B --> C["Send When Ready"] C --> D["Handlers React"] D --> E["App Stays Clean!"] style E fill:#4CAF50,color:white

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.