[mod_python] PythonPath and importer in 3.3

Dirk van Oosterbosch, IR labs labs at ixopusada.com
Tue Feb 6 18:00:40 EST 2007

Thanks for the quick response, guys.
especially Graham! I certainly don't want to deprive you from your  
holiday mood. So, if you're still reading this, clap down your laptop  
and enjoy the sun!

> I think you just need to list both directories in new import path.
> PythonOption mod_python.importer.path ["/Users/me/Sites/www/ 
> python/","/Users/me/Sites/www/python/templates"]
(	PythonOption mod_python.importer.path "['/Users/me/Sites/www/ 
python', '/Users/me/Sites/www/python/templates']"
as I understood it needed extra quotes on the outside.)

Indeed. This solves the problem I had.

Then using
   module = apache.import_module(template_name)
works and also everything in the chain of inheritance gets loaded  
(and shows up in the log!)

However, I am not sure I am 100% happy with adding the path to the  
templates directory to the directive in httpd.conf. I rather add the  
extra module-search-directories in the hander module (main.py in my  
case) itself, possibly determining which directory is extra needed,  
based on the request. Is there a function to add to the importer path  
from a module itself?

> BTW, where is framework.py. Is it in your '.../www.python' directory
> and thus would it be getting imported by mod_python importer even if
> by 'import' rather than import_module()? If it is, that it may be
> using 'import' should be okay.

Well, the problem wasn't with importing framework.py. I think I  
explained it a bit lousy. The problem was with the import statement  
*inside* framework.py. My Cheetah inheritance system works like this:
[...]/www/python/templates/specialized_item.tmpl (compiled into .py)
[...]/www/python/templates/page.tmpl (compiled into .py)
[...]/www/python/templates/FrameworkViewComponents.tmpl (compiled  
into .py)
[...]/www/python/templates/BaseSkeleton.tmpl (compiled into .py)
in which specialized_item.tmpl is the first one in the inheritance  
chain, being loaded with apache.import_module() and in which  
BaseSkeleton.tmpl is my base class Cheetah template.

The problem was the line
from FrameworkViewComponents import FrameworkViewComponents
in framework.py, but this is now solved with the extended  
PythonOption directive in httpd.conf.

Nevertheless, another, *minor* problem popped up, which didn't pop up  
I also have a template called image.tmpl (and compiled image.py) in  
Now, with MP3.3 this gives a problem when using the Python Image  
Library (PIL) and Image.py  Unfortunately the importer cannot  
discriminate between image.py and Image.py. Is there a way to  
explicitly call python import function and have it search only the  
PythonPath? (i.e. *not* the mp importer path first?)
Otherwise I'll have to rename the template, no biggie.

Finally, especially addressing Graham: please don't let these issues  
trouble your mind in any way. Happy holidays!
And thanks a lot for all the response,


>>> My initial setup was like this:
>>> in httpd.conf:
>>> ====================
>>> <IfModule mod_python.c>
>>> 	PythonPath "sys.path + ['/Users/me/Sites/www/python/']"
>>> 	PythonTransHandler translate
>>> ...
>>> in the .htaccess file in .../www/python/:
>>> ====================
>>> AddHandler mod_python .py
>>> PythonHandler main
>>> Then in main.py (the main handler which is called for every  
>>> request):
>>> ====================
>>> # for loading a Cheetah template
>>> templatesFolderLocation = "/Users/me/Sites/www/python/templates"
>>> if templatesFolderLocation not in sys.path:
>>> 	sys.path.append(templatesFolderLocation)
>>> ...
>>> modulename = 'page'
>>> ...
>>> try:
>>> 	module = __import__(modulename, globals(), locals(), [modulename])
>>> except ImportError:
>>> 	...
>>> templateClass = getattr(module, name)
>>> As said, this code works. Though it is not very nice and clean,  
>>> and I
>>> understood I had to go this way, while I was waiting for mod_python
>>> 3.3. Now I got python 3.3 and I read the documentation about
>>> apache.import_module() and about PythonPath, and I want to change  
>>> the
>>> code so it will make proper use of the new importer.
>>> The first thing I noticed in the docs is that the PythonPath
>>> shouldn't contain paths which are in the document tree.
>> This is only really an issue if the modules in the directory in the
>> document tree are being imported directly by mod_python importer
>> by reference in Python*Handler, by mod_python.publisher or by
>> direct use by apache.import_module(). If the modules in said
>> directory aren't being included in this way, it is okay to list
>> a subdirectory somewhere in the document tree in PythonPath.
>> The important thing is that you want to avoid having modules imported
>> through both mechanisms.
>> One step to ensure that anything in a directory isn't used by  
>> mod_python
>> in some way inadvertantly by mod_python.publisher, is to add into the
>> directory a .htaccess file containing:
>>   deny from all
>> If using own handler, not so big a deal.
>> I have managed to get Cheetah to use mod_python importer from  
>> within its
>> generated code before. The trick is to use import_module() instead of
>> __import__ to import the Cheetah template top level code file.
>> Ie., don't use:
>>   module = __import__(modulename, globals(), locals(), [modulename])
>> use:
>>   module = apache.import_module('/actual/path.py')
>> Then have the templates directory in:
>>   PythonOption mod_python.importer.path ['/actual/path/to/templates']
>> Try playing with that. If after my nine hour flight to next airport
>> I find some free internet access, I'll have a look to see how you  
>> went.
>> Anyway, hope I didn't muddle that because of being in a hurry.
>> :-) :-) :-) :-)
>> Graham
>>> http://www.modpython.org/live/mod_python-3.3.0b/doc-html/app- 
>>> changes-
>>> from-3.2.10.html :
>>>> The PythonPath directive MUST not be used to point at directories
>>>> within the document tree.
>>> So I changed the PythonPath line in httpd.conf into
>>> 	PythonOption mod_python.importer.path "['/Users/dirk/Sites/www/
>>> python']"
>>> But &#8211;as somewhat expected&#8211; this breaks the Cheetah  
>>> module
>> importing
>>> code.
>>> I tried to change it according to the docs
>>> (these http://www.modpython.org/live/mod_python-3.3.0b/doc-html/ 
>>> pyapi-
>>> apmeth.html )
>>> So now the code in main.py looks like this:
>>> ====================
>>> # for loading a Cheetah template
>>> templatesFolderLocation = "/Users/me/Sites/www/python/templates"
>>> # not appending to sys.path anymore
>>> ...
>>> modulename = 'page'
>>> ...
>>> try:
>>> 	module = apache.import_module(modulename, path=
>>> [templatesFolderLocation])
>>> except ImportError:
>>> 	... # importing the module fails here!
>>> templateClass = getattr(module, name)
>>> The reason for the failing import seems to be the inheritance system
>>> of the templates. Inside the chain of Cheetah modules that are
>>> inheriting eachother, there is a pure python module (framework.py),
>>> residing in /www/python (not in /www/python/templates/ !) which  
>>> tries
>>> to import a module from /www/python/templates/ through this line:
>>> 	from baseTemplate import baseTemplate
>>> I believe this fails and is the origin of my new problem.
>>> I thought the module search path, which I supplied with the path=
>>> argument in import_module() was copied forward to all subsequent
>>> imports, but it seems this does not work for me.
>>> Now I would be happy to add the templates directory to the python
>>> path again, but as I understood this is not the proper new  
>>> mod_python
>>> way.
>>> However I am reluctant to change the importing mechanism in
>>> framework.py and make framework dependant on mod_python's apache,
>>> since I also want to be able to test the cheetah part of my system
>>> outside of apache.
>>> I hope I am missing something obvious. What would be the most clean
>>> and proper way to solve this issue?

More information about the Mod_python mailing list