Graham Dumpleton
grahamd at dscpl.com.au
Tue Jan 25 00:14:42 EST 2005
Jorey Bump wrote .. > Create 2 modules, in the same directory, named master.py and slave.py: > > master.py: > > import slave > > def hello(req): > return slave.hello > > slave.py: > > hello = "Hello, world!" > > Access http://host/master/hello and "Hello, world!" appears in the > browser. Now move the files into a subdirectory and access > http://host/subdir/master/hello. It throws up an error: > > ImportError: No module named slave > > What happened? It originally appeared as though a module could import > adjacent modules, but this failed in a subdirectory. The reason is that > the original directory was where the interpreter was defined (with no > PythonPath), and so was prepended to the module search path. It doesn't > matter where master.py is (as long as it accessible by the defined > interpreter), but slave.py must be in sys.path if it is to be imported > by a published module. > > This falls under the "perceived problem" category, in that it's not a > bug, but sure looks like one at first. My own practice for coping with > this is to set a PythonPath directive, appending a directory outside the > DocumentRoot from which I can reliably import modules and packages > specific to that interpreter or VirtualHost. As I gave as response to a recent question, this is possibly better solved by writing: import os from mod_python import apache directory = os.path.dirname(__file__) slave = apache.import_module("slave",[directory]) def hello(req): return slave.hello Everyone has their own personal opinions on how best to use mod_python. As to my own two cents worth, although mod_python uses Python, the environment which it is running under isn't like running Python from the command line. One is using it in the context of a web server and what people tend to expect in doing stuff with web servers is that they can use the same resource name in different locations of the URL namespace. Because people are using mod_python/Python specifically to build web applications, I believe that this expectation about using the same resource names in multiple places is an overriding factor and any design should accomodate this practice. Thus, I would suggest that best practice would be: 1. Only use the "import" statement to import modules which have been provided with Python, are installed into the "site-packages" directory or are clearly seperated out into a directory distinct from the document hierarchy. In this later case PythonPath should be used to denote where that directory is. 2. That sys.path should not ever include any directory which is a part of the document hierarchy. Unfortunately the way handlers are setup this is done by default. This can be avoided though by setting PythonPath explicity at the same point PythonHandler is defined. If PythonPath isn't being defined anyway to add in extra external directories containing application specific modules, then PythonPath should be set to "sys.path" to ensure the document directory isn't added. 3. Always use apache.import_module() to import relative code files which are contained within the document hierarchy. Because of (2) above, one wouldn't be able to rely on sys.path though, so one should calculate the exact directory that a code files resides in. This can be done by using __file__ as described above. The directory would then be supplied to the import module method to ensure that only that directory is searched. In other words, a clear distinction is drawn. If it is outside the document hierarchy, then "import" must be used with sys.path defining the search path. Because "import" is used, modules outside of document hierarchy must be uniquely named. Inside the document heirarchy always use import_module() and always define the exact directory you want something loaded from. Within the document hierarchy, rather than calling them modules, they should be seen as code files and duplicates should be allowed in different directories. All that now would need to be done is to fix import_module() so that it copes properly with loading from the document hierarchy code files with the same name in different directories. This isn't actually that hard to do, but at the moment we seemed to be bogged down in arguing about whether it is right or not. Graham
|