Running Python Flask on a local IIS (not Azure!) with wfastcgi.py

There are already a lot of resources dealing with how to setup Django with IIS, or configure IIS to support WSGI with various tools such as Helicon Zoo, isapi-wsgi, and FastCGI.

FastCGI looked good among others because I wanted to go with least 3rd party stack and the Microsoft distribute the wfastcgi.py through PTVS. However, there’s a still one problem. I couldn’t find the document explains how to set up a local IIS to work with FastCGI and Flask.

Thanks to PTVS, it’s already well implemented and provided. The PTVS contains the wfastcgi.py, and web.config which set required environments to run. Here’s more detailed step:

1. Install wfastcgi.py. The PTVS official homepage has the link to download wfastcgi.py MSI installer.

http://pytools.codeplex.com/downloads/get/920481

wfastcgi

The wfastcgi MSI installer creates local copies of wfastcgi.py to python installed directory as below:

wfastcgi-installed

2. Install FastCGI to IIS and add wfastcgi.py handler to it. The official PTVS page has the required command to ease the steps here:

http://pytools.codeplex.com/wikipage?title=wfastcgi

start /wait %windir%\System32\\PkgMgr.exe /iu:IIS-CGI

%windir%\system32\inetsrv\appcmd set config /section:system.webServer/fastCGI “/+[fullPath=’c:\Python27\python.exe’, arguments=’C:\Python27\Scripts\wfastcgi.py’]”

The wfastcgi.py MSI installer also seems to add the handlers above automatically if FastCGI is already configured, but it’s not sure. You can now see the FastCGI listed installed Python paths.

fastcgi

3. Now it’s time to edit the web.config for Flask/IIS. If you created the Flask project with PTVS addon, it already contains the required web.config to support deploy to Azure. However, in order to run it on local IIS, it needs a little modification. Let’s see the original web.config first PTVS generated.

<?xml version=”1.0″?>
<!– Generated web.config for Microsoft Azure. Remove this comment to prevent
modifications being overwritten when publishing the project.
–>
<configuration>
<system.diagnostics>
<trace>
<listeners>
<add type=”Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ name=”AzureDiagnostics”>
<filter type=”” />
</add>
</listeners>
</trace>
</system.diagnostics>
<appSettings>
<add key=”WSGI_ALT_VIRTUALENV_HANDLER” value=”FlaskWebProject1.app” />
<add key=”WSGI_ALT_VIRTUALENV_ACTIVATE_THIS” value=”%ROOTDIR%\env\Scripts\activate_this.py” />
<add key=”WSGI_HANDLER” value=”ptvs_virtualenv_proxy.get_virtualenv_handler()” />
<add key=”PYTHONPATH” value=”%ROOTDIR%” />
</appSettings>
<system.web>
<compilation debug=”true” targetFramework=”4.0″ />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true” />
<handlers>
<add name=”Python FastCGI” path=”handler.fcgi” verb=”*” modules=”FastCgiModule” scriptProcessor=”%INTERPRETERPATH%|%WFASTCGIPATH%” resourceType=”Unspecified” requireAccess=”Script” />
</handlers>
<rewrite>
<rules>
<rule name=”Static Files” stopProcessing=”true”>
<match url=”^/static/.*” ignoreCase=”true” />
<action type=”Rewrite” url=”^/FlaskWebProject1/static/.*” appendQueryString=”true” />
</rule>
<rule name=”Configure Python” stopProcessing=”true”>
<match url=”(.*)” ignoreCase=”false” />
<conditions>
</conditions>
<action type=”Rewrite” url=”handler.fcgi/{R:1}” appendQueryString=”true” />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Few things. First, I removed the <system.diagnostics> section which installs Azure diags listener. Second, the IIS cannot understand the %ROOTDIR% variable so you should convert it all absolute path for that server you about to run.

So it’ll look like this:

<appSettings>
<add key=”WSGI_ALT_VIRTUALENV_HANDLER” value=”FlaskWebProject1.app” />
<add key=”WSGI_ALT_VIRTUALENV_ACTIVATE_THIS” value=”D:\repo\web\FlaskWebProject1\FlaskWebProject1\env\Scripts\activate_this.py” />
<add key=”WSGI_HANDLER” value=”ptvs_virtualenv_proxy.get_virtualenv_handler()” />
<add key=”PYTHONPATH” value=”D:\repo\web\FlaskWebProject1\FlaskWebProject1” />
</appSettings>

The generated web.config has a python handler mapped, but the path also needs to be updated to point the direct wfastcgi.py path as follows:

<handlers>
<add name=”Python FastCGI” path=”handler.fcgi” verb=”*” modules=”FastCgiModule” scriptProcessor=”C:\Python34\python.exe|C:\Python34\Scripts\wfastcgi.py” resourceType=”Unspecified” requireAccess=”Script” />
</handlers>

It’s enough to edit a web.config. However, if you still encounter a strange 500 internal error, please make sure the local IIS has the URL Rewrite 2.0 module installed. In my case, whenever I tried to open the edited web.config from IIS manager, it gives me that “There was an error while performing this operation. … web.config” error so that I couldn’t open a web.config nor edit mapping handlers. Fortunately, I found those answers from SO and solved it by installing URL Rewrite 2.0 through the ‘Web Platform Installer’. Microsoft Download site also provides a standalone exe.

urlrewrite2

http://stackoverflow.com/questions/3701562/iis-7-5-cant-open-handler-mappings

http://stackoverflow.com/questions/22199424/asp-net-iis-web-config-there-was-an-error-while-performing-this-operation

Done. If the IIS successfully loaded web.config, then it’ll show the correctly mapped Python wfastcgi handler at ‘Handler Mappings’ as follows:

handler1 handler2

If you have any questions, please leave a comment. Thanks for reading.

11 thoughts on “Running Python Flask on a local IIS (not Azure!) with wfastcgi.py

  1. Dude, this is what i need, thanks man! now i have to fix the “setAclUser” error… i can’t publish the project by Visual studio 2013 -___-
    😀

  2. somehow I got this
    Error occurred while reading WSGI handler:

    Traceback (most recent call last):
    File “C:\Python27\Scripts\wfastcgi.py”, line 711, in main
    env, handler = read_wsgi_handler(response.physical_path)
    File “C:\Python27\Scripts\wfastcgi.py”, line 568, in read_wsgi_handler
    return env, get_wsgi_handler(handler_name)
    File “C:\Python27\Scripts\wfastcgi.py”, line 541, in get_wsgi_handler
    handler = handler()
    File “.\ptvs_virtualenv_proxy.py”, line 99, in get_virtualenv_handler
    execfile(activate_this, dict(__file__=activate_this))
    IOError: [Errno 2] No such file or directory: ‘C:\\Users\\user\\Documents\\Visual Studio 2015\\Projects\\FlaskWebProject1\\FlaskWebProject1\\env\\Scripts\\activate_this.py’

      1. Thanks for the reply! I’ve already resolved this, I messed with web.config file. But now I get 404 “The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.” I made a build using VS 2015, copied it to wwwroot, made it to an app in IIS. It looks like I’m missing some crucial (and obvious for more experienced users) step here.
        Sorry for noob questions.

  3. First of all thanks for the post, it helps to have this kind of information when it’s your first time deploying a flask app with iis. Now I have my application on Visual Studio, I Publish it to file system so I could simulate a deploy.
    I run iis and install all stuff. Follow the tutorial (I don’t have virtual env on my web.config, that’s a difference), put all like it says and I get:
    “No se pudo encontrar scriptProcessor en la configuración de aplicación de .”
    Maybe in handler mapping is something that is missing, how about handler.fcgi path? or have you cange something in requests restrictions?

    Thanks for all.

  4. Thanks for your post.
    I have a problem, I always get HTTP 500 error code from IIS. Below is my web config

    Could you please give some advise? Thanks many.
    By the way, I can deploy successfully on Apache.

    1. Could you be more specific? I haven’t updated this article for a while, but I think I should start now for more recent version of OSs as well as troubleshooting information.

  5. Hey, thanks for the tutorial.. I did follow that and it actually worked and then it stopped completly always giving the error scriptProcessor could not be found in application configuration.
    I checked and double checked my handlers and the fastcgi section in the Appliactonhosy.config. Any ideas why?!

    1. Hi, It’s been a while since I wrote the post so things might have been changed. The error message seems related to a path but I’m not sure. I’ll test again and update the post with more recent version and environment.

  6. Hi,

    after successfully create the mapping handler and browse the site generate below error
    Not Found
    The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

    1. I also got the 404 Not Found since my flask app is not a site but a sub application of my main site.
      I think it is the @app.route(‘/’) problem, but I don’t know how to fix it by url rewrite… anyone can suggest?

Leave a reply to victorvictorvictor Cancel reply