<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: dIANE</title>
    <description>The latest articles on DEV Community by dIANE (@dianephan).</description>
    <link>https://dev.to/dianephan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439244%2F20f82e07-14df-41dd-85df-43cf4d71956b.png</url>
      <title>DEV Community: dIANE</title>
      <link>https://dev.to/dianephan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dianephan"/>
    <language>en</language>
    <item>
      <title>How to implement WebSockets and kill switches in a Python application</title>
      <dc:creator>dIANE</dc:creator>
      <pubDate>Tue, 12 Aug 2025 20:18:09 +0000</pubDate>
      <link>https://dev.to/launchdarkly/how-to-implement-websockets-and-kill-switches-in-a-python-application-2l4g</link>
      <guid>https://dev.to/launchdarkly/how-to-implement-websockets-and-kill-switches-in-a-python-application-2l4g</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;High-traffic events, such as product launches or promotional campaigns, can strain an application's infrastructure, leading to degraded performance or downtime. Implementing &lt;a href="https://dev.to/home/flags/killswitch"&gt;kill switch flags using LaunchDarkly&lt;/a&gt; allows you to gracefully degrade non-essential features, ensuring core functionalities remain available.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll explore how to integrate LaunchDarkly kill switch flags into a Python application to manage traffic effectively during peak events.&lt;/p&gt;

&lt;p&gt;This project will show a sample social media feed that makes calls to a 3rd party API for unique profile avatars and show personalized recommendations. However, if the developer has to toggle the kill switch, then the social media feed will fall back to default avatar images and not serve personalized recommendations. A WebSocket is required to send the flag value from the server to the client side browser. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.6 or newer. If your operating system does not provide a Python interpreter, you can go to &lt;a href="//python.org"&gt;python.org&lt;/a&gt; to download an installer.&lt;/li&gt;
&lt;li&gt;Visual Studio Code or your favorite IDE. &lt;/li&gt;
&lt;li&gt;LaunchDarkly account. If you haven’t done so already, &lt;a href="https://app.launchdarkly.com/signup" rel="noopener noreferrer"&gt;create a free account&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set Up the Environment
&lt;/h2&gt;

&lt;p&gt;Clone the repository and switch over to the “kill-switch-event-starter” branch to follow along in this tutorial. &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/dianephan/kill-switch-event-traffic.git
cd kill-switch-event-traffic
git checkout kill-switch-event-starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Create and Activate a Virtual Environment
&lt;/h2&gt;

&lt;p&gt;Run the following commands in your terminal to clone the repository with starter code, install dependencies, and start the server.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;venv&lt;/span&gt; &lt;span class="n"&gt;venv&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt;  
&lt;span class="c1"&gt;# On Windows: venv\Scripts\activate
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;launchdarkly&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ai&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;python3&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Head over to &lt;a href="http://localhost:5000/" rel="noopener noreferrer"&gt;http://localhost:5000/&lt;/a&gt; to see the social media feed up and running. There are posts coming in from users, however everyone’s avatar is the same defaulted gif. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxaeverh6zhlbgcw0ivj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxaeverh6zhlbgcw0ivj.png" alt="default image and recommendations for a social media page" width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s integrate the LaunchDarkly SDK so that we can see the power of kill switches in action. &lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the developer environment for the Python application
&lt;/h2&gt;

&lt;p&gt;Make sure that you are currently in the virtual environment of your project’s directory in the terminal or command prompt. &lt;/p&gt;

&lt;p&gt;Create a file at the root of your project folder named &lt;em&gt;.env&lt;/em&gt; and add the following lines to define the environment variables. These are placeholder values, which you’ll be updating later with real ones.&lt;/p&gt;

&lt;p&gt;LAUNCHDARKLY_SDK_KEY="sdk-###############"&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure your LaunchDarkly kill switch flag
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://app.launchdarkly.com/login" rel="noopener noreferrer"&gt;LaunchDarkly app&lt;/a&gt;, click on “Flags” in the left navigation menu and then click one of the &lt;strong&gt;Create flag&lt;/strong&gt; buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs7v9r0iszcfo7edub45.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs7v9r0iszcfo7edub45.jpg" alt="LaunchDarkly dashboard to create a flag" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure your flag as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name your flag “show-avatars-and-reccs”. When you type in the &lt;strong&gt;Name&lt;/strong&gt;, the &lt;strong&gt;Key&lt;/strong&gt; field will automatically populate.&lt;/li&gt;
&lt;li&gt;Enter some text in the description field to explain the purpose of this flag: “Shut off calls to the 3rd-party API that generates avatars.”&lt;/li&gt;
&lt;li&gt;Select “Kill Switch” as the flag type. Selecting this option will automatically set up the flag variations for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Create Flag&lt;/strong&gt; at the bottom of this dialog.&lt;/p&gt;

&lt;p&gt;On the following screen, click the dropdown menu next to the “Test” environment. Copy the SDK key by selecting it from the dropdown menu and add it to the &lt;em&gt;.env&lt;/em&gt; file created earlier. &lt;/p&gt;

&lt;p&gt;For the sake of this project, the toggle will be switched on to show that the application is working and everyone on the social media feed has a unique avatar with personalized recommendations. &lt;/p&gt;

&lt;p&gt;Turn the flag on using the toggle switch. Then click the &lt;strong&gt;Review and save&lt;/strong&gt; button at the bottom.&lt;br&gt;
Add a comment and verify the name of the environment, then click the &lt;strong&gt;Save changes&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2un32tcnddex55vc3o5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2un32tcnddex55vc3o5.png" alt="feature flag dashboard to toggle a switch on" width="512" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the &lt;em&gt;app.py&lt;/em&gt; file and change the following line to match the name of the newly created flag key:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flag_key = "replace-key-here"&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Test the kill switch flag
&lt;/h2&gt;

&lt;p&gt;It's time to initialize and make calls to the LaunchDarkly Python SDK.&lt;/p&gt;

&lt;p&gt;In the index route, uncomment the lines of code that creates the &lt;code&gt;show_avatar&lt;/code&gt; function. This function will retrieve feature flag values from the LaunchDarkly client and determine the actions based on the flag logic. &lt;br&gt;
The sample lines of code defining the user "Sandy" are no longer needed, so remove them completely. &lt;/p&gt;

&lt;p&gt;Make sure that the index route looks like the code below:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Get feature flag values
&lt;/span&gt;    &lt;span class="n"&gt;show_avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ldclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;variation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;show_avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;avatar_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_random_avatar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# Recommendations are only shown if we get a real avatar
&lt;/span&gt;        &lt;span class="n"&gt;show_recommendations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;avatar_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://media.tenor.com/ocYNcAWYyHMAAAAM/99-cat.gif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;show_recommendations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="c1"&gt;# Generate social media feed
&lt;/span&gt;    &lt;span class="n"&gt;feed_posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_feed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;show_avatar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;avatar_image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;avatar_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;show_avatar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;show_avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;feed_posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;show_recommendations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;show_recommendations&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Scroll down to the main function at the bottom of the file and uncomment those lines of code as well. &lt;/p&gt;

&lt;p&gt;Head back to &lt;a href="http://localhost:5000/" rel="noopener noreferrer"&gt;http://localhost:5000/&lt;/a&gt; and click refresh to see the social media feed show personalized recommendations and make calls to a 3rd party API for unique profile images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjseyzgl0egio1sii2pk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjseyzgl0egio1sii2pk.png" alt="social media feed with different cat images as profile pictures and personalized recommendations" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! The social media feed is operating successfully as if everything is normal and there is no need to cut off any resources. &lt;/p&gt;

&lt;p&gt;However, the magic of kill switches can only be appreciated if you don’t have to click refresh on the page. Your users should also not be required to click refresh in order to continue enjoying the application. &lt;/p&gt;

&lt;h2&gt;
  
  
  Add a websocket to the Python application
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.fullstackpython.com/websockets.html" rel="noopener noreferrer"&gt;WebSockets&lt;/a&gt; need to be implemented to enable real-time two-way communication between the server and client-side browser. &lt;a href="https://socket.io/docs/v4/" rel="noopener noreferrer"&gt;SocketIO is a great Python library that can get the job done quickly with low latency&lt;/a&gt;. Without this library, the browser would not know about the flag changes and the user would have to manually refresh the page, which is a slow process and will not truly demonstrate the power of a kill switch flag. &lt;/p&gt;

&lt;p&gt;To have your website update immediately when a LaunchDarkly flag changes, you need to implement SocketIO as the real-time update mechanism between your back end and front end. The front end will wait and listen for the flag value changes in order to update the UI accordingly.&lt;/p&gt;

&lt;p&gt;In your terminal, run the following command to install the library. &lt;br&gt;
&lt;code&gt;pip install flask-socketio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the &lt;em&gt;app.py&lt;/em&gt; file and add the following import statements to the top of the file: &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_socketio&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emit&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;socketio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Below the &lt;code&gt;show_evaluation_result&lt;/code&gt; function, add a class named &lt;code&gt;FlagValueChangeListener&lt;/code&gt; to handle the values from the WebSocket:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlagValueChangeListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flag_value_change_listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag_change&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Notify all connected clients about the flag change
&lt;/span&gt;        &lt;span class="n"&gt;socketio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flag_update&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flag_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new_value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flag_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="nf"&gt;show_evaluation_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;When the kill switch flag is toggled on or off, the function will detect a flag change and emit a SocketIO event, while showing the evaluation results. &lt;/p&gt;

&lt;p&gt;Change the main Python script so that it matches the code below: &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;sdk_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*** Please set the LAUNCHDARKLY_SDK_KEY env first&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Initialize the LaunchDarkly client
&lt;/span&gt;    &lt;span class="n"&gt;ldclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdk_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ldclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;is_initialized&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*** SDK successfully initialized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Set up the evaluation context. This context should appear on your
&lt;/span&gt;    &lt;span class="c1"&gt;# LaunchDarkly contexts dashboard soon after you run the demo.
&lt;/span&gt;    &lt;span class="n"&gt;user_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; \
        &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;example-user-key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Sandy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;flag_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ldclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;variation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;show_evaluation_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sdk_key&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;change_listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FlagValueChangeListener&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ldclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;flag_tracker&lt;/span&gt; \
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_flag_value_change_listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;change_listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flag_value_change_listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;socketio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The LaunchDarkly SDK client is initialized to retrieve the flag value and evaluate the context. &lt;a href="https://launchdarkly.com/docs/sdk/features/flag-changes#python" rel="noopener noreferrer"&gt;Read more about how the SDK subscribes to flag changes on the documentation here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SocketIO library wraps the Flask app with a server that can now support both regular HTTP requests as done in Flask, as well as WebSocket connections required to operate in realtime. &lt;/p&gt;

&lt;h2&gt;
  
  
  Add the socket to the front end
&lt;/h2&gt;

&lt;p&gt;At this point, you'll need to add some code so the browser can listen for the event using SocketIO’s JavaScript client. Add the following JavaScript to the head tag in the &lt;em&gt;index.html&lt;/em&gt; file in the &lt;em&gt;templates&lt;/em&gt; folder: &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.socket.io/4.7.5/socket.io.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;io&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flag_update&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Optionally, check which flag changed and act accordingly&lt;/span&gt;
        &lt;span class="c1"&gt;// For now, just reload the page to reflect the new flag value&lt;/span&gt;
        &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;When the LaunchDarkly flag changes, your back end emits a &lt;code&gt;flag_update&lt;/code&gt; event via the SocketIO library. &lt;/p&gt;

&lt;p&gt;The front end listens for this event and reloads the page automatically, so users see the updated content immediately without a manual refresh needed.&lt;/p&gt;

&lt;p&gt;Navigate back to LaunchDarkly and disable your flag. Click &lt;strong&gt;Review and save&lt;/strong&gt; again as you did previously when you enabled it. This is the process you will use if you have to quickly kill external API calls. No more wasting resources when one part of your application is failing and you need to act fast! &lt;/p&gt;

&lt;h1&gt;
  
  
  What’s next for building with kill switches and WebSockets?
&lt;/h1&gt;

&lt;p&gt;In this post you’ve learned how to use the &lt;a href="https://launchdarkly.com/docs/sdk/server-side/python" rel="noopener noreferrer"&gt;LaunchDarkly Python SDK&lt;/a&gt; to add kill switch flags and WebSockets to your Flask web application. If you want to learn more about what you can do with kill switch flags, check out the following articles: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://launchdarkly.com/blog/fastapi-python-kill-switch-flag/" rel="noopener noreferrer"&gt;Add LaunchDarkly kill switches to a FastAPI app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://launchdarkly.com/blog/sinatra-ruby-launchdarkly-kill-switch-flags/" rel="noopener noreferrer"&gt;Quickly disable external API calls in your Sinatra application sing LaunchDarkly kill switch flags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://launchdarkly.com/blog/java-spring-boot-kill-switch-flags/" rel="noopener noreferrer"&gt;Implement Kill Switch Flags to a Spring Boot Application&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://discord.com/invite/launchdarklycommunity" rel="noopener noreferrer"&gt;Join us on Discord&lt;/a&gt;, send me an email at (&lt;a href="mailto:dphan@launchdarkly.com"&gt;dphan@launchdarkly.com&lt;/a&gt;), or &lt;a href="https://www.linkedin.com/in/diane-phan/" rel="noopener noreferrer"&gt;connect with me on LinkedIn&lt;/a&gt; and let us know what you're building.&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>learning</category>
      <category>flask</category>
    </item>
  </channel>
</rss>
