Python WSGI

Installation

  1. Open Web Platform Installer and install "Python project":
  2. Follow steps in "Creating generic WSGI project":
  3. Create wsgi.py file with the following content:
    def application(environ, start_response):
        """WSGI Application"""
        start_response('200 OK', [('Content-type','text/html')])
        yield '<h2>WSGI environment variables</h2>\n<pre><code>'
        sorted_envs = environ.keys()[:]
        sorted_envs.sort()
        for k in sorted_envs:
            yield '{0:<24}: {1}\n'.format(k, environ[k])
        yield '</code></pre>'
    Output of sample WSGI application:

Deployment

To deploy Python Tornado application you will need to install Python Hosting Package on a target server. Then just copy IIS web site from one machine to another.

web.config example

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <system.webServer>
  <heliconZoo>
   <application name="python.project" >
    <environmentVariables>
     <add name="VIRTUAL_ENV" value="%APPL_PHYSICAL_PATH%\venv" />
     <add name="PATH" value="%APPL_PHYSICAL_PATH%\venv\Scripts;%PATH%" />
     <add name="PYTHONPATH" value="%APPL_PHYSICAL_PATH%\venv\lib\site-packages;%APPL_PHYSICAL_PATH%\venv\lib;%APPL_PHYSICAL_PATH%;%APPL_PHYSICAL_PATH%\project" />
     <!-- generic wsgi app -->
     <add name="WSGI_APP" value="wsgi.application" />
     <!-- web console -->
     <!-- security rules for console are placed in /console/web.config -->
     <add name="CONSOLE_URL" value="console" />
     <!-- application deployment -->
     <add name="DEPLOY_FILE" value="deploy.py" />
     <!-- <add name="DEPLOY_LOG" value="deploy.log" /> -->
     <!-- logging -->
     <add name="ERROR_LOG_DIR"  value="log" />
     <!-- reload on files changes -->
     <!-- <add name="WATCH_FILE_CHANGES_MASK" value="*.py" /> -->
    </environmentVariables>
   </application>
  </heliconZoo>
  <handlers>
   <!-- Django or WSGI application over fastcgi -->
   <add name="python.project#x86" scriptProcessor="python.2.7.wsgi" path="*" verb="*" modules="HeliconZoo_x86" preCondition="bitness32" resourceType="Unspecified" requireAccess="Script" />
   <add name="python.project#x64" scriptProcessor="python.2.7.wsgi" path="*" verb="*" modules="HeliconZoo_x64" preCondition="bitness64" resourceType="Unspecified" requireAccess="Script" />
  </handlers>
 </system.webServer>
</configuration>

Environment variables

  • PYTHONPATH — path to Python modules. In the example it points to application root, the python_modules\Lib\site-packages subfolder and also includes value defined by user.
  • WSGI_APP — full path to the application’s entry point function.
  • WATCH_FILE_CHANGES_MASK — optional files mask to watch for changes. Worker is restarted every time a file of specified type changes. In the example all .py files are watched.

web.config to disable Python in directory with static files

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <!-- 
      This removes Helicon Zoo handler and makes IIS processing static files.
      -->
      <remove name="python.project#x64" />
      <remove name="python.project#x86" />
    </handlers>
  </system.webServer>
</configuration>

deploy.py file example

Deploy file is used to execute commands, such as components installations or database migrations, on a server when the application initially starts or updated. The following code is only an example. We recommend you to use deploy.py file that comes with the Python project template.

import sys
import os
import os.path


VIRTUALENV_EXE = os.path.join(os.path.dirname(sys.executable), 'scripts\\virtualenv.exe')
VIRTUALENV_NAME = 'venv'
DJANGO_PROJECT_NAME = 'project'
PROJECT_DIR = os.path.dirname(__file__)


def run(command, exit_on_error=True):
    print('\nRunning command: '+command)
    status = os.system(command)
    if status != 0:
        sys.exit(status)

def main():
    os.chdir(PROJECT_DIR)

    # update APPDATA env for pip
    #os.environ['APPDATA'] = os.path.join(PROJECT_DIR, PYTHON_MODULES_DIR)

    # create virtual environment
    if not os.path.exists(VIRTUALENV_NAME):
        run(VIRTUALENV_EXE+' '+VIRTUALENV_NAME)

    # install requirements to local folder
    run('pip install --requirement=requirements.txt')

    # that's all
    print "Bye!"

if __name__=='__main__':
    main()