Getting web.py working properly on Dreamhost was a real pain, especially since the wiki article on the subject was flat out wrong in several places. I ended up choosing to use fcgi for talking to apache, which is good for performance but not optimal for development work (you sometimes have to kill the process and restart it for changes to take effect). This is generally ok, since the built in web.py dev server works for local code debugging.
To use web.py 0.3 with fcgi on Dreamhost:
- Enable FCGI in the Dreamhost panel. If you don’t do this, nothing will work! It can take a while (half an hour) to become enabled.
- Download and unpack the web.py package to your working directory (or put it in your python path)
- Download fcgi.py and put it in your path
- Modify web/wsgi.py to replace the runfcgi function with this:
def runfcgi(func, addr=('localhost', 8000)): """Runs a WSGI function as a FastCGI server.""" import fcgi as flups return flups.WSGIServer(func, multiplexed=False, bindAddress=addr).run() - Create your .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?(.*)$ dispatch.fcgi/$1 [L] - Create your
dispatch.fcgi(see below) and chmod it 755
You have several options for your dispatch.cgi file. Mine looks like this:
#!/usr/bin/python2.5
import code
code.app.run()
Your dispatch.fcgi WILL NOT WORK if you use dos newlines, and it must not be group or world writeable. My web.py entry point (called code.py) contains (near the bottom):
if __name__ == "__main__":
app.run() #this is normally only called from dispatch.cgi
else:
web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
This allows me to use the built in web.py server for local testing while the same file works flawlessly on the server. There’s another (less good) option for this at the end of the post.
I had trouble getting web.py set up to work with the django templating system. It was raising a RuntimeError: Settings already configured. It turns out (obviously in retrospect) that web.py loads your main code more than once, and running the settings.configure command as recommended in the django documentation fails the second time. The solution is to put it within a try (or your dispatch.fcgi if it is set up like mine):
from django.conf import settings
try:
settings.configure(DEBUG=True,
TEMPLATE_DEBUG=True,
TEMPLATE_DIRS=('/templates', ))
except:
pass
from django.template.loader import render_to_string
Below is an alternative and less good approach for getting web.py working. Some may find it slightly easier. I dislike it.
- Rename your entry point (the tutorial calls it
code.py) todispatch.fcgi - Insert the line:
!#/usr/bin/python2.5at the top. - Add the line:
web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)right above the
if __name__ == "main":line. - Copy your new
dispatch.fcgitodispatch.py. From now on, every time you change one, you must update the other to match. - Make SURE your copy of
dispatch.fcgion the server is executable, but is not group or world writable (chmod 755).
If you’re having trouble, try running dispatch directly from the command line:
$ ./dispatch.fcgi
Often this will tell you more than a cryptic 500 error. Also be sure to check your apache logs.
Comments
Why is fcgi.py recommended over flup?
Posted 18 Oct 2009 at 6:07 AM ¶I know of no reason that flup should not work equally well. I think at the time that I wrote this, there was some incompatibility between flup and something installed on dreamhost, but this has probably since been resolved.
I use flup for everything now, but I don’t generally host my python on dreamhost anymore, so…
Posted 18 Oct 2009 at 11:37 AM ¶I have installed the web.py in a subdomain of my website hosted by dreamhost and would like to make it work for the subdomain. Everything is setup as suggested. on the ssh shell commandline ./dispatch.fcgi result in http://0.0.0.0:8080/. but when I do it from the browser http://..com/ it does not work..I expected ‘Hello World’
code.py is as follows:
import sys, os
sys.path.append(os.getcwd()+’/py_libs’)
import web
urls=(
‘/(.*)’,'index’
)
class index:
def GET(self):
return “Hello World”
app=web.application(urls,globals())
if __name__ == “__main__”:
app.run() #this is normally only called from dispatch.cgi
#else:
# web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
.htaccess is as follows:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?(.*)$ dispatch.fcgi/$1 [L]
What might be wrong? Please help
Posted 26 Jul 2010 at 8:51 AM ¶Post a Comment