On 06/03/2015, at 6:55 AM, Ronny Pfannschmidt <[email protected]>
wrote:
> in reference to my tweet,
>
> unlike other deployments, mod_wsgi cant be configured with a python home and
> a entrypoint
>
> that makes various forms of deployment a bit more painfull, i already saw the
> mod_wsgi express thing and
> i'm curious about how deployments would look with it as well
So two questions.
Q1. Why can't mod_wsgi be configured with a PYTHONHOME.
A1. It can. Important to realise though is that mod_wsgi is compiled against a
specific Python version. Although you can change PYTHONHOME effectively used,
you can only refer it to Python virtual environment baed on the same Python
installation that mod_wsgi was compiled for.
Now there are a few ways that PYTHONHOME could be overridden.
The first is to set PYTHONHOME via an environment variable in the scripts used
to startup Apache, or in the 'envvars' file that Apache Software Foundation
distributions read. If supported this is usually in the same directory as the
'apachectl' script. Linux distributions tend to do away with 'envvars' and so
what init script you stick it in depends on the Linux distribution.
The second is to set the WSGIPythonHome directive in the Apache configuration
file. This will override it for embedded mode and daemon mode processes in one
go.
The third if using daemon mode is to set the python-home option to the
WSGIDaemonProcess directive. This will override it just for that daemon process
group.
Yes the mod_wsgi documentation is out of date about all this, but for a very
long time there wasn't really a point updating it as the Linux distributions
were shipping such old versions that they didn't support the python-home option
to WSGIDaemonProcess.
Python module search paths and best way of referring to Python virtual
environments is described in:
http://blog.dscpl.com.au/2014/09/python-module-search-path-and-modwsgi.html
Q2. Why can't mod_wsgi be given a Python module path, with optional callable
name within that. Eg., 'mydjangosite.wsgi:application'.
A2. The reason in part for this is because of how Apache works. The basic
method Apache uses for mapping URLs to applications is to map the URL to a file
system path. The file system path is important because it serves as part of
Apache's security mechanism around whether a web application served in some way
by a resource at a specific location can actually be accessed. So mod_wsgi was
designed primarily around working properly with Apache and abiding by its
security mechanism rather than side stepping them, which would have been what
was required if trying to mount a WSGI application where the identifier was
simply a module path and name for the application.
There is also another more obscure reason relating to lessons from the mess of
a way that mod_python handled things. In mod_python it would treat any file it
found with a .py extension in the file system mappable by a URL as a module and
import it as a module. This meant it had to add the directory it was in to the
Python module search path. This broke apart and bad things would happen when
you had two sub directories mappable by a URL and both had a file in them
called index.py. Suddenly you would have two modules called 'index' on the
search path and when accessing the second it would use the first instead and
the wrong code would be executable. So trying to mix module style imports with
file system mappable URLs was a bad idea.
I spent a lot of time coming up with a solution for that in mod_python which
was rather complicated but solved the problem. Rather amusingly, some time
after mod_python effectively died as far as Apache Software Foundation was
concerned, one of the original primary authors tried to resurrect mod_python
and because they didn't understand what the code I had added was for and what
the problem was, they resurrected the broken away of doing things and so
whatever the latest mod_python version is now suffers all the original problems
I fixed.
So the WSGI script file is not intended to be like a module and when named it
doesn't use the base name path of the file. That is for 'index.wsgi', the
__name__ attribute of the module is not 'index', nor it is accessible at
sys.modules['index']. I even discourage the use of the .py extension and
instead recommend .wsgi. This is because if the same directory was added to the
Python module search path and you were using 'index.py' and imported 'index',
you would cause a double important of the module as the latter import would
load it as 'index'. This can cause various problems if the WSGI script file
does initialisation which shouldn't be repeated.
A WSGI script file should therefore be treated more like the main script file
for a program, a way of setting up the application, albeit it wouldn't then run
some non returning code. As soon as the WSGI script file is imported, it would
be kept in memory and then requests passed off to the application.
A notable thing about how the WSGI script file is loaded is that unlike a
module import, the Python global import lock is not held. This is the same as
if a Python main script file is loaded. That the Python global import lock is
not held means it is safe to start up background threads from the WSGI script
file which then run and start doing module imports. You cannot safely do this
if it was used like a normal Python module.
Although it doesn't seem like a big issue it is, as the fact that many WSGI
servers only allow you to specify a module and imports it as a module, means
they can't be used to properly setup the environment. They therefore have to
resort to special server ready hook functions which are executed after the fact
to work around it.
So overall I would argue what mod_wsgi does is a better solution.
Note that this doesn't stop you from using a WSGI application imported from
another module, it just means you use a WSGI script file to do the import.
The best way therefore of setting things up for Django is therefore not to
refer to the generated 'wsgi.py' file Django generates for you, but to create a
separate 'django.wsgi' file which if necessary sets up any extra environment
variables to handle running under mod_wsgi and then does an 'from
mydjangosite.wsgi import application'.
The whole generated 'wsgi.py' in Django has been a pain as it actually set
people up for using Django in a bad way with mod_wsgi and contributed to the
wrong belief expressed by many that one can't set environment variables for
mod_wsgi to use. You can set environment variables, but you would set them in
the WSGI script file before then importing your Django application from the
generated wsgi.py file.
So you say these issues as you perceived them make deployment more painful. Can
you explain how you have your Apache/mod_wsgi configuration set up and whether
you are using a separate WSGI script file as an intermediary between mod_wsgi
and your separate WSGI application as intended and is best practice, or are you
trying to refer direct to a generated module such as the wsgi.py in Django?
I will handle mod_wsgi-express in a separate message.
Graham
--
You received this message because you are subscribed to the Google Groups
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.