Forums

PasteDeploy errors

I have been trying to get this working for a while with no luck.

Following instructions from the project site, I have the following.

wsgi.py

from paste.deploy import loadapp
application = loadapp('config:/home/barnsey/sites/sites.ini')

sites.ini

[composite:main]
use = egg:Paste#urlmap
/ = home
/qtile = qtile
[app:home]
use = egg:Paste#static
document_root = %(here)s/htdocs
[app:qtile]
use = egg:Paste#static
document_root = /home/barnesc/sites/qtile/docs

error.log

2012-11-21 16:37:07,404 :Traceback (most recent call last):
2012-11-21 16:37:07,405 :  File "/usr/local/lib/python2.7/site-packages/paste/urlmap.py", line 201, in __call__
2012-11-21 16:37:07,405 :    environ['SCRIPT_NAME'] += app_url
2012-11-21 16:37:07,405 :KeyError: 'SCRIPT_NAME'

I don't have much experience with the nginx+uwsgi that I believe PAW is using, but is there a missing uwsgi_param SCRIPT_NAME xxx directive?

I'm sure I remember reading somewhere that mod_wsgi always sets SCRIPT_NAME even if it's empty because the WSGI spec requires it, but I'm afraid I can't find the reference. Anyway, perhaps it's one of those things that mostly doesn't matter but paste is being slightly fussier (or perhaps more correct) and requiring.

I tried adding the variable to the environment to no effect.

wsgi.py

from paste.deploy import loadapp
from os import putenv
putenv('SCRIPT_NAME', '')
application = loadapp('config:/home/barnsey/sites/sites.ini')

Any suggestions on how to do this would be much appreciated.

Ahh, I was thinking this had to be done at the nginx level (i.e. by the PAW staff). This is an only slightly educated guess as to the problem, though!

Interesting, I would have thought that putting the putenv('SCRIPT_NAME', '') in wsgi.py would fix it. I'll take a more in-depth look and get back to you.

OK, it should be fixed now. Definitely an odd one; Cartroo is right that it does have to be set at the nginx level -- but I still can't figure out why it's not getting passed down to the app when it's set in uwsgi or in your wsgi.py, as those should both be equivalent.

Anyway, the fix is in now and hopefully it should all work...

Awesome, that did the job, thanks.

Thanks for confirming! I'll make sure it gets into the codebase so that it keeps working after the next release :-)

And many thanks to Cartroo once again!

If you take a look at the Python docs for os.environ, you can see that it's not too surprising that using os.putenv() didn't work as the environment is captured once at start-up - after that point, you have to modify os.environ directly to affect other parts of the script which use the environment. Also, if paste does its init at import time (I'm not sure whether it does, but it wouldn't be unreasonable) then the value would need to be set prior to the import statement.

I agree that it's a bit of a mystery why setting it at the uwsgi level doesn't work, however. Perhaps some issue with configuration files not being re-read, or the Python environment not being fully re-initialised? Again, if paste does some work at import time then the interpreter would need to be restarted for any change to take effect.

Thanks Cartroo, I did see this doc and tried both ways,

From what you have said, might have worked?

wsgi.py

import os
os.putenv('SCRIPT_NAME', '')
os.environ['SCRIPT_NAME'] = ''
from paste.deploy import loadapp
application = loadapp('config:/home/barnsey/sites/sites.ini')

Possibly, but it's only a guess - I don't have any solid evidence. I think the nginx configuration is arguably the correct place anyway, because that's the layer in which all the applications are multiplexed.

I tried the os.environ['SCRIPT_NAME'] = '' option too, but it didn't work. Odd!

In which case perhaps paste itself is a red herring and uwsgi is actually the software which requires the setting? That would explain why it has to be set at the nginx level. If I had a make a guess at this point, perhaps it's something like a failure to set it at the nginx level has a knock-on effect which means that paste doesn't work down the line - I'm assuming it can't be as simple as uwsgi simply requiring it as that would mean no WSGI hosting would work.

Perhaps uwsgi expectes to be passed the value from nginx, which it then modifies in some way and passes on to the WSGI application itself in the environment. I guess if the WSGI application doesn't use the setting, nobody would ever notice if it wasn't being set. Perhaps if uwsgi expects the value to be passed in this way it doesn't allow it to be set in its own configuration on the assumption that it's only the hosting sever which can correctly set it.

Unfortunately this is all supposition and I'm not really in a position to experiment with my home nginx setup right now, but if anybody does figure out more detail as to what's going on here, it would be good to post it here for reference.

I will post anything we find. The odd thing is that the settings we're using for uwsgi are the package defaults -- so the fact that something apparently necessary isn't being set in there seems really odd.

I agree it's definitely rather surprising, although "necessary" is maybe a bit strong - perhaps paste is the only library which relies on it being set, and others determine the path some other way?

It's hard to say. I did find several pages (including, I think, one in the WSGI spec -- sorry, I don't have the URLs to hand) that seemed to be implying that setting that variable was a requirement. But perhaps it's not, or it's not widely implemented.

Sometimes it does seem that these middleware implementers treat the word "MUST" as largely equivalent to "SHOULD", "MAYBE" and "IF NOBODY COMPLAINS DON'T WORRY ABOUT IT". (^_^)

Still, Ian Bicking seems like a good egg, so he's probably done things by the book.