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.

Reply via email to