<?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: William Sousa</title>
    <description>The latest articles on DEV Community by William Sousa (@willmvs).</description>
    <link>https://dev.to/willmvs</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%2F188264%2F31bf2d67-00b3-461e-9e6c-1d9823666213.jpg</url>
      <title>DEV Community: William Sousa</title>
      <link>https://dev.to/willmvs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/willmvs"/>
    <language>en</language>
    <item>
      <title>Flask on Windows using Apache</title>
      <dc:creator>William Sousa</dc:creator>
      <pubDate>Sun, 02 Aug 2020 01:49:26 +0000</pubDate>
      <link>https://dev.to/willmvs/flask-deployment-on-windows-139b</link>
      <guid>https://dev.to/willmvs/flask-deployment-on-windows-139b</guid>
      <description>&lt;p&gt;Flask is a Python based micro-framework, which can be used to create dynamic websites, APIs, and many other applications.&lt;/p&gt;

&lt;p&gt;Despite all Linux cloud options you might have a customer with a Windows environment, that would rather use their existing system than setting a Linux one. No problem, right? But how do we deploy a Flask app to production Windows?&lt;/p&gt;

&lt;p&gt;As I faced many issues when I had this challenge, I thought listing the steps and some of the problems would be a good topic for my first post on Dev.to.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://flask.palletsprojects.com/en/1.1.x/deploying/" rel="noopener noreferrer"&gt;deployment documentation&lt;/a&gt; states "Flask’s built-in server is not suitable for production as it doesn’t scale well", so you need a WSGI server to deploy your Flask application to production.&lt;/p&gt;

&lt;p&gt;I will start using Apache + mod_wsgi, and later add more posts to the series covering other options. &lt;/p&gt;

&lt;h1&gt;
  
  
  Flask deployment on Windows using Apache and mod_wsgi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Install Apache
&lt;/h2&gt;

&lt;p&gt;Go with the recommended distribution from &lt;a href="https://www.apachelounge.com/download" rel="noopener noreferrer"&gt;Apache Lounge&lt;/a&gt;. I downloaded version 2.4.43 Win64 as a zip file. There was a warning saying "Be sure you installed latest 14.xx &lt;strong&gt;Visual C++ Redistributable&lt;/strong&gt; for Visual Studio 2015-2019", and they provide direct download links for it. Make sure to download the appropriate &lt;code&gt;vc_redist&lt;/code&gt; x64 or x86, matching the Apache version you got, in my case x64.&lt;/p&gt;

&lt;p&gt;Install the &lt;code&gt;vc_redist&lt;/code&gt; and then unzip Apache to the default location &lt;code&gt;C:\Apache24&lt;/code&gt;. If you select a different location take note as we'll need it later.&lt;/p&gt;

&lt;p&gt;To test Apache, open a command prompt, &lt;code&gt;cd C:\Apache24\bin&lt;/code&gt;. Then issue this command to start Apache:&lt;br&gt;
&lt;code&gt;httpd.exe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After you press Enter, it will tell you if there are any errors. Open a browser and go to &lt;code&gt;http://localhost&lt;/code&gt;. You should see a page saying "It works!". You can shut down Apache by pressing &lt;code&gt;Ctrl+C&lt;/code&gt; (it may take a few seconds). &lt;br&gt;
The &lt;code&gt;ReadMe.txt&lt;/code&gt; file on Apache's zip file has more information and examples, including how to run it as a Windows service.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install mod_wsgi
&lt;/h2&gt;

&lt;p&gt;You need the &lt;strong&gt;mod_wsgi&lt;/strong&gt; Python package as the middle man to show Apache how to handle Python applications. &lt;/p&gt;

&lt;p&gt;Assuming you already have Python installed, mod_wsgi can be installed using &lt;code&gt;pip install mod_wsgi&lt;/code&gt; on the command prompt. However, some of its dependencies might make it tricky.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Apache location
&lt;/h3&gt;

&lt;p&gt;If you didn't install Apache on the default location, you might get this error after the &lt;code&gt;pip install mod_wsgi&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

RuntimeError: No Apache installation can be found. Set the MOD_WSGI_APACHE_ROOTDIR environment to its location.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If that's the case, use the set command. For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

set "MOD_WSGI_APACHE_ROOTDIR=F:/Apache24"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ensure you specify the path with a forward slash, like the example. This is only needed when doing the install.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Microsoft Visual C++ Build Tools
&lt;/h3&gt;

&lt;p&gt;After that, if you try the &lt;code&gt;pip install mod_wsgi&lt;/code&gt; again, you might receive a long error, but the most important part is this one:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    building 'mod_wsgi.server.mod_wsgi' extension
    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual
C++ Build Tools": https://visualstudio.microsoft.com/downloads/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;mod_wsgi will be compiled on your Windows host, so it has a dependency on Microsoft Visual C++ Build Tools. Note the &lt;em&gt;Build Tools&lt;/em&gt; are different than the &lt;em&gt;Redistributable&lt;/em&gt; that you installed on step 1. &lt;/p&gt;

&lt;p&gt;Go to the &lt;a href="https://visualstudio.microsoft.com/downloads/" rel="noopener noreferrer"&gt;Visual Studio&lt;/a&gt; download page, expand &lt;em&gt;Tools for Visual Studio&lt;/em&gt;, and click the download link for the &lt;em&gt;Build Tools&lt;/em&gt; (currently 2019). Execute the installer, select &lt;em&gt;C++ build tools&lt;/em&gt;, on the right side you can un-check some optional features, but you need at least &lt;em&gt;MSVC v142&lt;/em&gt; and &lt;em&gt;Windows 10 SDK&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3vokzn2k2eyd4si2vpbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3vokzn2k2eyd4si2vpbd.png" alt="Microsoft Visual C++ Build Tools installer"&gt;&lt;/a&gt;&lt;br&gt;
After the install is complete you will have to reboot Windows.&lt;/p&gt;

&lt;p&gt;Finally, try the &lt;code&gt;pip install mod_wsgi&lt;/code&gt; again and it should work. &lt;br&gt;
If you still face errors, on the Start menu look for "Developer Command Prompt for VS 2019", and use it to issue the &lt;code&gt;pip install mod_wsgi&lt;/code&gt;. It will have the correct PATH with the VC++ Build Tools and should avoid setup issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Flask app setup
&lt;/h2&gt;

&lt;p&gt;Assuming you already know Flask, and installed it on your Windows using &lt;code&gt;pip install flask&lt;/code&gt;, there a few considerations for structuring your app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The general recommendation is to set your app to act like a Python package, so create a folder containing at least a &lt;code&gt;__init__.py&lt;/code&gt; with the main code. &lt;/li&gt;
&lt;li&gt;Another option, is to use an empty &lt;code&gt;__init__.py&lt;/code&gt; and the main code on another .py file on the same folder.&lt;/li&gt;
&lt;li&gt;As a Python package, avoid using '-' on your folder name, otherwise you might face syntax errors when importing your app later. This &lt;a href="https://stackoverflow.com/questions/761519/is-it-ok-to-use-dashes-in-python-files-when-trying-to-import-them" rel="noopener noreferrer"&gt;StackOverflow question&lt;/a&gt; gives more details about it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.1 Sample app and structure
&lt;/h3&gt;

&lt;p&gt;Here is the &lt;code&gt;__init__.py&lt;/code&gt; sample I used for this article:&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&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&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="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;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello Flask under Apache!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&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="n"&gt;app&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here is the project structure for this sample:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

C:\git\
+-- yourapp
|   +-- __init__.py          
+-- wsgi_scripts
|   +-- yourapp.wsgi


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case my app 'package' is called yourapp.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Create your .wsgi file
&lt;/h3&gt;

&lt;p&gt;To run your application you need a wsgi file. In my sample I have &lt;code&gt;yourapp.wsgi&lt;/code&gt;. Note that I stored this file on a separate folder. Storing the wsgi file on the same folder as you Flask app works as well, but &lt;a href="https://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html#mounting-the-wsgi-application" rel="noopener noreferrer"&gt;is not recommended&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A minimal wsgi file (which is Python code):&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;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yourapp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;sys.path.insert&lt;/code&gt; should point to the location that contains the folder with your app.&lt;/li&gt;
&lt;li&gt;Use double backslashes on your &lt;code&gt;sys.path.insert&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Configure Apache httpd.conf
&lt;/h2&gt;

&lt;p&gt;On the command prompt, issue: &lt;code&gt;mod_wsgi-express module-config&lt;/code&gt; , the output should be similar to:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

LoadFile "c:/program files/python37/python37.dll"
LoadModule wsgi_module "C:/Users/prod_deploy/AppData/Roaming/Python/Python37/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/program files/python37"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copy the output and paste it on your &lt;code&gt;C:\Apache24\conf\httpd.conf&lt;/code&gt;. I suggest putting it after the existing &lt;code&gt;LoadModule&lt;/code&gt; directives.  &lt;/p&gt;

&lt;p&gt;At the end of the same &lt;code&gt;httpd.conf&lt;/code&gt; file, add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Include Flask file
Include conf/yourapp.conf


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;yourapp&lt;/code&gt; with the name of the configuration file you want to use. With this, we will have the Flask VirtualHost configuration on a separate file, avoiding mistakes. &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Create the yourapp.conf
&lt;/h2&gt;

&lt;p&gt;On your Apache install folder, navigate to the conf subfolder, e.g. &lt;code&gt;C:\Apache24\conf&lt;/code&gt;, and create the &lt;code&gt;yourapp.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;A minimal sample file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;VirtualHost *:80&amp;gt;
    ServerName flaskwill.com
    WSGIScriptAlias / C:/git/wsgi_scripts/yourapp.wsgi
    &amp;lt;Directory C:/git/yourapp&amp;gt;
        Require all granted
    &amp;lt;/Directory&amp;gt;
&amp;lt;/VirtualHost&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;On VirtualHost, change 80 to a different port if needed. &lt;/li&gt;
&lt;li&gt;ServerName should list the server's IP address or a DNS name&lt;/li&gt;
&lt;li&gt;WSGIScriptAlias has two arguments, the first is the website path which will be associated with the wsgi file, in this example / or the root. The second argument is the absolute path to the wsgi file. In this example, when I access flaskwill.com/ it will execute my yourapp.wsgi. &lt;/li&gt;
&lt;li&gt;Directory should point to the folder with your Flask app files. Note the 'Require all granted' to give Apache (version 2.4 or later) access to the files and sub-folders. Older versions of Apache use a different syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Start Apache and test your app
&lt;/h2&gt;

&lt;p&gt;After covering all steps, start Apache (or restart it if already running), so it will read the conf files and load your app.&lt;br&gt;
Open a browser and enter &lt;code&gt;http://localhost&lt;/code&gt; and your Flask app should show up. If you set a DNS address like the flaskwill I used, you will have to update the real DNS to point to your server, or you could update your Windows &lt;code&gt;hosts&lt;/code&gt; file to test it locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;I hope this is useful for someone, but remember this is just &lt;strong&gt;one&lt;/strong&gt; way of doing it, as I am sure there are other methods of deploying Flask. &lt;br&gt;
I appreciate any feedback so I can improve this post and learn for the next ones.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi/" rel="noopener noreferrer"&gt;https://flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/GrahamDumpleton/mod_wsgi" rel="noopener noreferrer"&gt;https://github.com/GrahamDumpleton/mod_wsgi&lt;/a&gt;&lt;br&gt;
&lt;a href="https://modwsgi.readthedocs.io/en/develop/index.html" rel="noopener noreferrer"&gt;https://modwsgi.readthedocs.io/en/develop/index.html&lt;/a&gt;&lt;br&gt;
&lt;a href="http://httpd.apache.org/docs/2.4/" rel="noopener noreferrer"&gt;http://httpd.apache.org/docs/2.4/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>flask</category>
      <category>windows</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
