[mod_python] Current Working Directory not set?

Graham Dumpleton grahamd at dscpl.com.au
Fri Jan 27 16:04:14 EST 2006


On 28/01/2006, at 6:53 AM, Sean Jamieson wrote:

> Hello everybody,
> I don't know if there's already been a discussion about this, it seems 
> like a small but obvious issue.

Many times. ;-)

> The current working directory does not apear to be set when a 
> mod_python.publisher script runs; or rather it's set to "/" which is 
> not useful. This becomes quite a pain, as I'm forced to do many things 
> to work around it.

As someone else said, working directory can't be changed because of 
multithreading
abilities of mod_python.

> i.e.
> 1) I've started using kid templates, and I have to use:
>     Template( file=req.document_root().'template.kid', ... )
> or
>    Template( 
> file=req.document_root().'project_dir/templates/template.kid', ... )
> rather then the more natural:
>    Template( file='templates/template.kid )
> this should find the 'templates' directory in the same directory as 
> the running script

Don't use req.document_root(). Instead, in that specific Python code 
file,
include at global scope:

   import os
   __here__ = os.path.dirname(__file__)
   __templates__ = os.path.join(__here__,"templates")

That will give you the directory that file is located in, in a handy 
variable
which you can then use.

     Template( file=os.path.join(__templates__,"template.kid") )

This is only useful though if all your publisher handlers are in the 
one directory.
If you have stuff spread over subdirectories, you start having to use 
relative
paths as appropriate in subdirectory handler files.

   import os
   __here__ = os.path.dirname(__file__)
   __templates__ = os.path.join(__here__,"..","templates")

Thus, you may be better off doing something like:

   def _templates(req,path):
     return os.path.join(req.hlist.directory,"templates",path)

   ...

     Template( file=_template("template.kid") )

The req.hlist.directory variable will be set to the directory for which 
PythonHandler
is specified, thus giving you a root anchor point which you can use to 
describe all
paths relative to. Doing this means you have more flexibility as far as 
moving code
files around between directories without having to modify code.

The other reference point you might use is:

   def _templates(req,path):
     directory = os.path.dirname(req.filename)
     return os.path.join(directory,path)

   ...

     Template( file=_template("templates/template.kid") )

The req.filename object is similar to using __file__ for most cases, 
but getting the
information from the request object instead.

You might even create your own derived class from Kid's Template class 
so you can
pass it a 'req' object and relative template file path and have that 
derived class
constructor do the calculation of where the file is relative to 
PythonHandler root
or req.filename.

In other words, to be more transparent, the template system would need 
to know about
the environment it is used in.

> 2) I have to fully qualify imports from the document root, as the 
> document root is added to sys.modules, but the current directory is 
> not. So, if I'm in a subdirectory under the document root I have to 
> do:
>    import project_dir.subpackage.module
> when the current directory is 'project_dir'. This is silly, I should 
> be able to import something in, or under, the current working 
> directory:
>    import subpackage.module

If these packages contain reusable code used across various pages and 
don't have
actual code in them for generating pages, it is not a good idea to put 
them under
your document root. This is because with the right URL they may be able 
to be
invoked by a remote user because of publishers automatic mapping. Thus 
you need to
be very careful.

If they do contain code for generating pages, you should not be using 
"import"
to access them as at the same time they could be getting loaded by 
publisher using
a different module loading system which will cause various problems.

As suggested by someone else, look at using "apache.import_module()".

> I would have to do some hack involving seperating the dirname of 
> __file__ and adding it to sys.modules

I think you must have meant into sys.path. Same above, Modifying 
sys.path directly
in mod_python is not usually a good idea either. The use of 
PythonHandler will
automatically put that root directory in sys.path for you without 
having to resort
to using PythonPath. This all assumes you have already set PythonPath 
explicitly
and aren't using Location directive instead of Directory directive to 
specify context
in which mod_python is used.

Graham



More information about the Mod_python mailing list