Can someone explain why this code shows a new version of Python on Dreamhost ?
import sys,os
# Force Passenger to run our virtualenv python
INTERP = "/home/site/env/bin/python"
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)
def application(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return ["Hello, world!" + sys.version]
While this code shows an old version :
#!/home/site/env/bin/python
import sys
def application(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return ["Hello, world!" + sys.version]
If you throw some debugging code in passenger_wsgi.py to write out a log file:
x = open(os.path.expanduser('~/log.log'), 'w')
x.write(repr(sys.argv))
x.close()
and then examine ~/log.log, then you’ll find that the python process that loads passenger_wsgi.py is started by running /dh/passenger/lib/phusion_passenger/wsgi/request_handler.py.
The first line of /dh/passenger/lib/phusion_passenger/wsgi/request_handler.py is
#!/usr/bin/env python
and it loads passenger_wsgi.py by calling
app_module = imp.load_source('passenger_wsgi', 'passenger_wsgi.py')
Since passenger_wsgi.py is loaded as a Python module, the #!/home/site/env/bin/python line at the start of your second passenger_wsgi.py file is treated simply as a Python comment and ignored. The default /usr/bin/python is used instead.
The recommended fix for this is exactly what your first passenger_wsgi.py does: execl the version of Python you actually want. I usually compile Python 2.7 in the shell user’s home directory and use that.
PS: If you’re curious I have some notes about setting up Django on Dreamhost so that you can do continuous deployment…
Related
I'm using Bottle for a Python project and I've set the project to run on the localhost:8080 (Windows 10 laptop). I’ve coded the project on VS Code, however, when I start the debugger on VS Code’s integrated terminal,I am presented with Error 500 on my browser (Google Chrome).
The project worked fine on a TA's machine, however on my laptop, bottle isn't routing to the index page, even when I explicitly had it import it from the static_file and adding the root file to the ‘run’ function. I tried running the example from Bottlepy.org, and even that isn’t working.
The only thing that has worked was:
from bottle import run, route
#route('/')
def hello():
return "If you're seeing this message, then bottle is working"
run(host='localhost', port=8080)
Again, I’ve ran:
from bottle import run, route, template
#route('/')
def hello():
return template("index.html")
run(host='localhost', port=8080)
and
from bottle import run, route, static_file
#route('/static/')
def hello():
return static_file('index.html', root='static')
run(host='localhost', port=8080)
Including the example from bottlepy.org, to which resulted in:
Error 500 Template 'index.html' not found.
Or
Error 500 ‘Template ‘/’ not found
I don’t believe it’s a PATH issue with Python, but it could be a JSON file issue with VS code. All the Python packages on my machine are updated and I’m out of ideas at the moment. Your suggestions/recommendations would be appreciated. Thank you.
Probably the issue is because the integrated shell executes the code in some other directory where the file 'index.html' is.
To help solve the issue, replace the file name with an absolute path, e.g.
#route('/static/')
def hello():
return static_file(os.path.join(os.path.dirname(__file__), 'index.html'), root='static')
I'm new to Python and i have looked around on how to import my custom modules from a directory/ sub directories. Such as this and this.
This is my structure,
index.py
__init__.py
modules/
hello.py
HelloWorld.py
moduletest.py
index.py,
# IMPORTS MODULES
import hello
import HelloWorld
import moduletest
# This is our application object. It could have any name,
# except when using mod_wsgi where it must be "application"
def application(environ, start_response):
# build the response body possibly using the environ dictionary
response_body = 'The request method was %s' % environ['REQUEST_METHOD']
# HTTP response code and message
status = '200 OK'
# These are HTTP headers expected by the client.
# They must be wrapped as a list of tupled pairs:
# [(Header name, Header value)].
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))]
# Send them to the server using the supplied function
start_response(status, response_headers)
# Return the response body.
# Notice it is wrapped in a list although it could be any iterable.
return [response_body]
init.py,
from modules import moduletest
from modules import hello
from modules import HelloWorld
modules/hello.py,
def hello():
return 'Hello World from hello.py!'
modules/HelloWorld.py,
# define a class
class HelloWorld:
def __init__(self):
self.message = 'Hello World from HelloWorld.py!'
def sayHello(self):
return self.message
modules/moduletest.py,
# Define some variables:
numberone = 1
ageofqueen = 78
# define some functions
def printhello():
print "hello"
def timesfour(input):
print input * 4
# define a class
class Piano:
def __init__(self):
self.type = raw_input("What type of piano? ")
self.height = raw_input("What height (in feet)? ")
self.price = raw_input("How much did it cost? ")
self.age = raw_input("How old is it (in years)? ")
def printdetails(self):
print "This piano is a/an " + self.height + " foot",
print self.type, "piano, " + self.age, "years old and costing\
" + self.price + " dollars."
But through the Apache WSGI, I get this error,
[wsgi:error] [pid 5840:tid 828] [client 127.0.0.1:54621] import
hello [wsgi:error] [pid 5840:tid 828] [client 127.0.0.1:54621]
ImportError: No module named hello
Any idea what have I done wrong?
EDIT:
index.py
__init__.py
modules/
hello.py
HelloWorld.py
moduletest.py
User/
Users.py
You should have an __init__.py file in the modules/ directory to tell Python that modules is a package. It can be an empty file.
If you like, you can put this into that __init__.pyto simplify importing your package's modules:
__all__ = ['hello', 'HelloWorld', 'moduletest']
From Importing * From a Package
Now what happens when the user writes from sound.effects import *?
Ideally, one would hope that this somehow goes out to the filesystem,
finds which submodules are present in the package, and imports them
all. This could take a long time and importing sub-modules might have
unwanted side-effects that should only happen when the sub-module is
explicitly imported.
The only solution is for the package author to provide an explicit
index of the package. The import statement uses the following
convention: if a package’s __init__.py code defines a list named
__all__, it is taken to be the list of module names that should be imported when from package import * is encountered. It is up to the
package author to keep this list up-to-date when a new version of the
package is released. Package authors may also decide not to support
it, if they don’t see a use for importing * from their package.
You need to set the path to your application in the .wsgi file, which in your case it seems to be index.py:
import sys
path = '/full/path/to/app'
if path not in sys.path:
sys.path.insert(0, path)
You could also fix this in your apache virtualhost config:
WSGIDaemonProcess example home=/path/to/mysite.com python-path=/path/to/mysite.com
See http://blog.dscpl.com.au/2014/09/python-module-search-path-and-modwsgi.html for more info.
In your code hello.py only contains a method, if you wrapped it in a class that would be seen as a module.
I'm really enjoying Bottle so far, but the fact that I have to CTRL+C out of the server and restart it every time I make a code change is a big hit on my productivity. I've thought about using Watchdog to keep track of files changing then restarting the server, but how can I do that when the bottle.run function is blocking.
Running the server from an external script that watches for file changes seems like a lot of work to set up. I'd think this was a universal issue for Bottle, CherryPy and etcetera developers.
Thanks for your solutions to the issue!
Check out from the tutorial a section entitled "Auto Reloading"
During development, you have to restart the server a lot to test your
recent changes. The auto reloader can do this for you. Every time you
edit a module file, the reloader restarts the server process and loads
the newest version of your code.
This gives the following example:
from bottle import run
run(reloader=True)
With
run(reloader=True)
there are situations where it does not reload like when the import is inside a def. To force a reload I used
subprocess.call(['touch', 'mainpgm.py'])
and it reloads fine in linux.
Use reloader=True in run(). Keep in mind that in windows this must be under if __name__ == "__main__": due to the way the multiprocessing module works.
from bottle import run
if __name__ == "__main__":
run(reloader=True)
These scripts should do what you are looking for.
AUTOLOAD.PY
import os
def cherche(dir):
FichList = [ f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir,f)) ]
return FichList
def read_file(file):
f = open(file,"r")
R=f.read()
f.close()
return R
def load_html(dir="pages"):
FL = cherche(dir)
R={}
for f in FL:
if f.split('.')[1]=="html":
BUFF = read_file(dir+"/"+f)
R[f.split('.')[0]] = BUFF
return R
MAIN.PY
# -*- coding: utf-8 -*-
#Version 1.0 00:37
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import datetime
import ast
from bottle import route, run, template, get, post, request, response, static_file, redirect
#AUTOLOAD by LAGVIDILO
import autoload
pages = autoload.load_html()
BUFF = ""
for key,i in pages.iteritems():
BUFF=BUFF+"#get('/"+key+"')\n"
BUFF=BUFF+"def "+key+"():\n"
BUFF=BUFF+" return "+pages[key]+"\n"
print "=====\n",BUFF,"\n====="
exec(BUFF)
run(host='localhost', port=8000, reloader=True)
I've worked through installing Python as a CGI application on IIS on Windows 7. This is pretty straightforward, but I'd like to use the WSGI stuff, for better flexibility.
I downloaded the archive for isapi_wsgi, unzipped it, and then ran the install as per the instructions, like this:
\python27\python.exe setup.py install
This succeeded:
Then I coded a .py module that had the wsgi glue in it, and tried installing it. This failed like so:
It's a COM Moniker error, and I know that the IIS6-compatible management stuff is based on COM Monikers, which reminded me that there is a pre-req for isapi_wsgi of the IIS6-compatible management stuff. I ran \windows\system32\OptionalFeatures.exe and installed that, then re-ran the .py module and it installed correctly.
C:\dev\wsgi>\Python27\python.exe app1_wsgi.py
Configured Virtual Directory: /wsgi
Installation complete.
Ok, wonderful. Now when I look in the current directory, I see a new DLL named _app1_wsgi.dll, and when I look in IIS Manager I can see a new IIS vdir, and a scriptmap within that vdir for '*', which is mapped to the _app1_wsgi.DLL. All good. But! making a request to http://localhost/wsgi gives me a 500 error.
Through some trial-and-error I see that the .py module that defines my handlers must be in the site-packages directory. I am very surprised by this.
Can I avoid this? Can I simply put the .py module in the same directory as the generated .dll file? Or do I need to deploy all of my python logic to site-packages in order to run it from the WSGI mechanism?
The answer is:
the installation of isapi_wsgi as described in the question, is correct.
with the basic boilerplate of app.py as shown in the example code accompanying isapi_wsgi, the python classes for the web app need to be in the site-packages directory.
it is possible to allow the python source modules to reside in the same directory as with the generated *.dll file, but it requires some special handling in the *wsgi.py file.
a better way to run python on Windows for development purposes is to simply download the Google App Engine and use the builtin dedicated http server. The framework that comes with the GAE SDK handles reloading and allows the .py modules to be placed in particular directories.
If you don't want to download and install the GAE SDK, then you might try the following. Using this code, when a request arrives on isapi_wsgi, the handler looks in the home directory for a py module, and loads it. If the module is already loaded, it checks the file "last modified time" and reloads the module if the last mod time is later than the time from the prior load. It works for simplistic cases but I suppose it will be brittle when there are nested module dependencies.
import sys
import os
import win32file
from win32con import *
# dictionary of [mtime, module] tuple; uses file path as key
loadedPages = {}
def request_handler(env, start_response):
'''Demo app from wsgiref'''
cr = lambda s='': s + '\n'
if hasattr(sys, "isapidllhandle"):
h = None
# get the path of the ISAPI Extension DLL
hDll = getattr(sys, "isapidllhandle", None)
import win32api
dllName = win32api.GetModuleFileName(hDll)
p1 = repr(dllName).split('?\\\\')
p2 = p1[1].split('\\\\')
sep = '\\'
homedir = sep.join(p2[:-1])
# the name of the Python module is in the PATH_INFO
moduleToImport = env['PATH_INFO'].split('/')[1]
pyFile = homedir + sep + moduleToImport + '.py'
fd = None
try:
fd = win32file.CreateFile(pyFile, GENERIC_READ, FILE_SHARE_DELETE, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
except Exception as exc1:
fd = None
if fd is not None:
# file exists, get mtime
fd.close()
mt = os.path.getmtime(pyFile)
else:
mt = None
if mt is not None:
h = None
if not pyFile in loadedPages:
# need a new import
if homedir not in sys.path:
sys.path.insert(0, homedir)
h = __import__(moduleToImport, globals(), locals(), [])
# remember
loadedPages[pyFile] = [mt, h]
else:
# retrieve handle to module
h = loadedPages[pyFile][1]
if mt != loadedPages[pyFile][0]:
# need to reload the page
reload(h)
loadedPages[pyFile][0] = mt
if h is not None:
if 'handler' in h.__dict__:
for x in h.handler(env, start_response):
yield x
else:
start_response("400 Bad Request", [('Content-Type', 'text/html')])
else:
start_response("404 Not Found", [('Content-Type', 'text/html')])
yield cr()
yield cr("<html><head><title>Module not found</title>" \
"</head><body>")
yield cr("<h3>404 Not Found</h3>")
yield cr("<h3>No handle</h3></body></html>")
else:
start_response("404 Not Found", [('Content-Type', 'text/html')])
yield cr()
yield cr("<html><head><title>Module not found</title>" \
"</head><body>")
yield cr("<h3>404 Not Found</h3>")
yield cr("<h3>That module (" + moduleToImport + ") was not found.</h3></body></html>")
else:
start_response("500 Internal Server Error", [('Content-Type', 'text/html')])
yield cr()
yield cr("<html><head><title>Server Error</title>" \
"</head><body><h1>Server Error - No ISAPI Found</h1></body></html>")
# def test(environ, start_response):
# '''Simple app as per PEP 333'''
# status = '200 OK'
# start_response(status, [('Content-type', 'text/plain')])
# return ['Hello world from isapi!']
import isapi_wsgi
# The entry point(s) for the ISAPI extension.
def __ExtensionFactory__():
return isapi_wsgi.ISAPISimpleHandler(request_handler)
def PostInstall(params, options):
print "The Extension has been installed"
# Handler for our custom 'status' argument.
def status_handler(options, log, arg):
"Query the status of the ISAPI?"
print "Everything seems to be fine..."
if __name__=='__main__':
# This logic gets invoked when the script is run from the command-line.
# In that case, it installs this module as an ISAPI.
#
# The API provided by isapi_wsgi for this is a bit confusing. There
# is an ISAPIParameters object. Within that object there is a
# VirtualDirs property, which itself is a list of
# VirtualDirParameters objects, one per vdir. Each vdir has a set
# of scriptmaps, usually this set of script maps will be a wildcard
# (*) so that all URLs in the vdir will be served through the ISAPI.
#
# To configure a single vdir to serve Python scripts through an
# ISAPI, create a scriptmap, and stuff it into the
# VirtualDirParameters object. Specify the vdir path and other
# things in the VirtualDirParameters object. Stuff that vdp object
# into a sequence and set it into the ISAPIParameters thing, then
# call the vaguely named "HandleCommandLine" function, passing that
# ISAPIParameters thing.
#
# Clear as mud?
#
# Seriously, this thing could be so much simpler, if it had
# reasonable defaults and a reasonable model, but I guess it will
# work as is.
from isapi.install import *
# Setup the virtual directories -
# To serve from root, set Name="/"
sm = [ ScriptMapParams(Extension="*", Flags=0) ]
vdp = VirtualDirParameters(Name="wsgi", # name of vdir/IIS app
Description = "ISAPI-WSGI Demo",
ScriptMaps = sm,
ScriptMapUpdate = "replace"
)
params = ISAPIParameters(PostInstall = PostInstall)
params.VirtualDirs = [vdp]
cah = {"status": status_handler}
# from isapi.install, part of pywin32
HandleCommandLine(params, custom_arg_handlers = cah)
Using this model, requesting http://foo/wsgi/bar will try loading bar.py from the home directory with the WSGI .dll file. If bar.py cannot be found, you get a 404. If bar.py has been updated since the last run, it reloads. If bar cannot be loaded, you get a 500.
bar.py must export a method called handler, publicly. That method must be a generator. like so:
import time
def handler(env, start_response):
start_response("200 OK", [('Content-Type', 'text/html')])
cr = lambda s='': s + '\n'
yield cr("<html><head><title>Hello world!</title></head><body>")
yield cr("<h1>Bargle Bargle Bargle</h1>")
yield cr("<p>From the handler...</p>")
yield cr("<p>(bargle)</p>")
yield cr("<p>The time is now: " + time.asctime() + " </p>")
yield cr("</body></html>")
__all__ = ['handler']
But as I said, I think GAE is probably a better way to develop Python webapps using Windows.
put this on top of your scrip:
import site
site.addsitedir('path/to/your/site-packages')
the same problem you had, was solved with this two lines
I'm trying to get a trivial Django project working with Passenger on Dreamhost, following the instructions here
I've set up the directories exactly as in that tutorial, and ensured that django is on my PYTHONPATH (I can run python and type 'import django' without any errors). However, when I try to access the url in a browser, I get the following message: "An error occurred importing your passenger_wsgi.py". Here is the contents of my passenger_wsgi.py file:
import sys, os
sys.path.append("/path/to/web/root/") # I used the actual path in my file
os.environ['DJANGO_SETTINGS_MODULE'] = ‘myproject.settings’
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
However, when I put the following simple "Hello World" application in passenger_wsgi.py, it works as intended, suggesting Passenger is set up correctly:
def application(environ, start_response):
write = start_response('200 OK', [('Content-type', 'text/plain')])
return ["Hello, world!"]
What am I missing? Seems like some config issue.
Are those fancy quotation marks also in your code?
os.environ['DJANGO_SETTINGS_MODULE'] = ‘myproject.settings’
^ ^
If so, start by fixing them, as they cause a syntax error.