If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

DISCLAIMER: this recipe is experimental (since the new method to build web2py will be in the near future switching to bbfreeze)...there will be minor edits if some tests will fail.

This guide details all the steps to build the binary with the "legacy" py2exe and the "new" bbfreeze. The end-goal is get rid of py2exe (slighly outdated) and adopt bbfreeze to build web2py binaries.

There's a little contest you can partecipate...rules:

you need to edit the setup_exe.py enabling it to generate the windows binary release with bbfreeze - including the executable for the gevented server - and send to niphlod [at] the big g your revised setup_exe.py as an attachment.

I'll review the scripts and the first one will be thanked in the official CHANGELOG for the next stable web2py version.

 

How to build web2py windows binaries

I assume you're starting from scratch, and that you want to build web2py 2.7.3 (ATM, latest stable release) in a fresh Windows computer.

All the below links are for the latest packages available ATM.

First of all, we need python :

- grab the python installer for 2.7.5 at http://www.python.org/ftp/python/2.7.5/python-2.7.5.msi

Run the setup, and you'll have python installed....next one, we need easy_install and pip.

- install setuptools (requirement for pip)

   - download https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py and save to a directory of your choice
     - run python ez_setup.py
- install pip

    - download https://raw.github.com/pypa/pip/master/contrib/get-pip.py and save to a directory of your choice
    - run python get-pip.py

- to enable typing "python" instead of c:\python\python (and pip instead of c:\python\scripts\pip) every time, add c:\python27\ and c:\python27\scripts\ to PATH

We have pip, let's check that we have the latest setuptools and pip
- pip install --upgrade setuptools
- pip install --upgrade pip

For some web2py modules, python-win32 is needed to work with all features enabled
- install python-win32
    - http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win32-py2.7.exe/download

Of course, we need web2py source. Grab it and put under a directory of your choice.

Here we are with the minimum requirements to run web2py "source" on Windows.

Windows binaries are built with additional (but not required) packages to work better in the Windows world:

- install psycopg2 from http://www.stickpeople.com/projects/python/win-psycopg/2.5.1/psycopg2-2.5.1.win32-py2.7-pg9.2.4-release.exe
- install pyodbc from http://pyodbc.googlecode.com/files/pyodbc-3.0.7.win32-py2.7.exe
- install ldap from https://pypi.python.org/packages/2.7/p/python-ldap/python-ldap-2.4.13.win32-py2.7.msi

You now have two choices: build the binary with the "legacy" method (py2exe) or with the bran new one (bbfreeze).

Py2exe "legacy"

We need py2exe:

- install py2exe from http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe/download

Now, copy extras/build_web2py/setup_exe.py and extras/build_web2py/setup_exe.conf to the root directory (where web2py.py is). Make sure you copy them from trunk (the 2.7.3 stable release doesn't ship with the latest version of those files)

Open a shell in the web2py.py directory and run

python setup_exe.py py2exe

After a little bit, you should have a web2py_win.zip that is the archive containing the build. As any other software "freezed" with python > 2.5, you need to make sure that Microsoft Visual C++ 2008 Redistributable Package is on the computer running the binary or you need to ship the DDLs (if you have rights to do so) with the binary itself. Look at the official binary to see the structure of the Microsoft.VC90.CRT dir

bbfreeze "new"

We need to install bbfreeze with all its dependencies
 - easy_install bbfreeze

Now, copy extras/build_web2py/setup_exe.py and extras/build_web2py/setup_exe.conf to the root directory (where web2py.py is). Make sure you copy them from trunk (the 2.7.3 stable release doesn't ship with the latest version of those files)

Open a shell in the web2py.py directory and run

python setup_exe.py bbfreeze

After a little bit, you should have a web2py_win.zip that is the archive containing the build. As any other software "freezed" with python > 2.5, you need to make sure that Microsoft Visual C++ 2008 Redistributable Package is on the computer running the binary or you need to ship the DDLs (if you have rights to do so) with the binary itself. Look at the official binary to see the structure of the Microsoft.VC90.CRT dir

Serving with a gevented webserver web2py on Windows

Web2py ships with anyserver.py that enables web2py to be served with many webservers.... it's really basic though it can be reaaaally useful to see how easy is running web2py with something else than rocket.

This is a revision of anyserver.py that allows to run web2py in a gevented webserver, with SSL.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import optparse

if '__file__' in globals():
    path = os.path.dirname(os.path.abspath(__file__))
elif hasattr(sys, 'frozen'):
    path = os.path.dirname(os.path.abspath(sys.executable))
else:
    path = os.getcwd()
os.chdir(path)

sys.path = [path] + [p for p in sys.path if not p == path]

from gevent import pywsgi
from gevent.pool import Pool
from gevent import monkey
monkey.patch_all()

def run(options):
    import gluon.main
    if options.password != '<recycle>':
        gluon.main.save_password(options.password, int(options.port))
    if options.logging:
        application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase,
                                            logfilename='httpserver.log',
                                            profiler_dir=profiler)
    else:
        application = gluon.main.wsgibase
    address = (options.ip, int(options.port))
    workers = options.workers
    spawn = workers and Pool(int(options.workers)) or 'default'
    ssl_args = dict()
    if options.ssl_private_key:
        ssl_args['keyfile'] = options.ssl_private_key
    if options.ssl_certificate:
        ssl_args['certfile'] = options.ssl_certificate
    server = pywsgi.WSGIServer(
                    address, application, 
                    spawn=spawn, log=None,
                    **ssl_args
                    )
    server.serve_forever()

def main():
    usage = 'python web2py_gevent.py -i 127.0.0.1 -p 8000 -a "<recycle>"'
    try:
        version = open('VERSION','r')
    except IOError:
        version = ''
    parser = optparse.OptionParser(usage, None, optparse.Option, version)
    msg = ('password to be used for administration '
           '(use -a "<recycle>" to reuse the last password))')
    parser.add_option('-a',
                      '--password',
                      default='<recycle>',
                      dest='password',
                      help=msg)
    
    parser.add_option('-c',
                      '--ssl_certificate',
                      default='',
                      dest='ssl_certificate',
                      help='file that contains ssl certificate')

    parser.add_option('-k',
                      '--ssl_private_key',
                      default='',
                      dest='ssl_private_key',
                      help='file that contains ssl private key')
    
    parser.add_option('-l',
                      '--logging',
                      action='store_true',
                      default=False,
                      dest='logging',
                      help='log into httpserver.log')
    
    parser.add_option('-F',
                      '--profiler',
                      dest='profiler_dir',
                      default=None,
                      help='profiler dir')
                      
    parser.add_option('-i',
                      '--ip',
                      default='127.0.0.1',
                      dest='ip',
                      help='ip address')
                      
    parser.add_option('-p',
                      '--port',
                      default='8000',
                      dest='port',
                      help='port number')
                      
    parser.add_option('-w',
                      '--workers',
                      default=None,
                      dest='workers',
                      help='number of workers')

    (options, args) = parser.parse_args()
    print 'starting on %s:%s...' % (
        options.ip, options.port)    
    run(options)

if __name__ == '__main__':
    main()

Copy it and save as web2py_on_gevent.py in the root dir.

You can now run web2py on gevent with

python web2py_on_gevent.py

Contest

Here starts the little contest: we want to use something a little bit more powerful than the rocket webserver to serve applications using the binary. bbfreeze allows us to add gevent to the binary in an easy way....but you need to find out by yourself how to do it (to win the contest :-P) . You must build web2py with bbfreeze following the previous steps AND build also the web2py_on_gevent.py executable that will serve web2py on gevent in the windows binary.

Related slices

Comments (1)

  • Login to post



  • 0
    brianm 8 years ago

    Seems to work as advertised - will submit my binaries to niphlod to see if it's what was expected. Gevent ain't hard.

    replies (1)
    • brianm 8 years ago

      Hints:

      Install the Gevent (https://pypi.python.org/pypi/gevent#downloads) and greenlet (https://pypi.python.org/pypi/greenlet) Windows binaries.

      Make sure you've got C:\Bin\Microsoft.VC90.CRT (even if you've installed the VC++ redirstributables before it may not be in that same location - easy way out is to just grab them from an existing web2py binary's zip file)

      Some other minor edits need to be made to setup_exe.py - I'm assuming they'll be added to trunk soon. Move the section that copies the C:\Bin\Microsoft.VC90.CRT so it is after the section that runs bbfreeze. Uncomment the #f.addScript("web2py_gevent.py") line (and change the script name to web2py_on_gevent.py or else rename the script from the recipe to match).


Hosting graciously provided by:
Python Anywhere