Getting Mod_python Working
Copyright © Graham Dumpleton
This article is intended to assist newbies to mod_python in trying to get their first test program to work. It goes beyond what is provided in the mod_python documentation, attempting to describe common problems that can arise.
Note that this article is not intended to describe how to install mod_python itself. For instructions on installing mod_python, you should refer to the "README" file provided with the source code and/or the online documentation for such information.
Version Number
Before you even get started, it is important to know exactly which version of mod_python you are using. Having determined what version it is, make sure that you are referring to the correct version of the mod_python documentation. There are some subtle differences in configuring and using the main versions of mod_python which are available. Use the wrong documentation and it most likely will not work. The appropriate documentation is generally included with the mod_python source package or can be found on the mod_python web site.
The main versions of mod_python in use are 2.7, 3.0, 3.1 and 3.2. Version 3.0 and later require Apache 2.0, whereas version 2.7 can work on both Apache 1.3 or 2.0. To use Apache 2.2, you must use mod_python 3.2.10 or later.
If mod_python has been installed, you can determine which version is being used by executing Python from the command line and attempting to import the module mod_python.psp.
~ [510]$ python Python 2.3 (#1, Sep 13 2003, 00:49:11) [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import mod_python.psp
If you see a Python exception of the form:
ImportError: No module named _apache
it means that you have mod_python version 3.1 or later. If you see the Python exception:
ImportError: No module named psp
it means that you only have version 2.7 or 3.0. Finally, if you instead see the Python exception:
ImportError: No module named mod_python.psp
it means that mod_python isn't installed after all, or at least not for the version of Python you are trying to use.
In order to distinguish mod_python version 3.1 from version 3.2, additionally try importing the module mod_python.testhandler.
~ [510]$ python Python 2.3 (#1, Sep 13 2003, 00:49:11) [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import mod_python.testhandler
If you see a Python exception of the form:
ImportError: No module named _apache
it means that you have mod_python version 3.2. If you see the Python exception:
ImportError: No module named testhandler
it means that you only have version 3.1.
From version 3.2 onwards of mod_python, a version string is provided in the mod_python module. Thus, this string can also be accessed to obtain the version of mod_python being used.
Python 2.3 (#1, Sep 13 2003, 00:49:11) [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import mod_python >>> mod_python.version '3.2.10'
Note that the fact that import errors are being raised is okay and exactly what is expected. This is because it isn't actually possible to use mod_python from Python when executed on the command line. What is important at this point is what error is displayed, as from that it can be determined which version of mod_python you are using.
You can also confirm which version of mod_python is being used by looking in the Apache error log file for the mod_python startup message:
[Tue Feb 01 16:08:21 2005] [notice] Apache/2.0.51 (Unix) mod_python/3.1.3 Python/2.3 configured -- resuming normal operations
If you do not see this message, then it can mean that Apache hasn't been configured to load the mod_python module. To solve this, the installation instructions will need to be followed to complete the installation. This will entail adding to the Apache configuration file a line similar to:
LoadModule python_module libexec/mod_python.so
The actual path to mod_python.so file may vary depending on your installation.
If the Apache configuration does contain this line, but you can't find the mod_python startup message, make sure that Apache has actually been restarted. This is necessary as Apache will only read this line when it is being started.
Basic Content Handler
To perform an actual test of mod_python, first create an empty subdirectory somewhere under your Apache document root directory. Do not simply use your document root directory as it will be easier to isolate problems and perform various tests if you use a subdirectory. By using a subdirectory, you also lesson the risk that you will stop your web server from serving up existing documents which you are hosting.
You will need to know what URL should be used to access this directory via your web server. To test that the URL you expect to work, does in fact work, create a file called "hello.txt" within that directory containing the text "hello.txt". Now access the corresponding URL for this file using your web browser to confirm that you can actually retrieve it.
If this doesn't work, make sure you are using the correct URL. Also ensure that the directory is actually visible through the web server and that the directory and the file contained within it are setup with appropriate permissions such that the user which Apache runs as, can access them.
There are now two ways which you can configure Apache to enable use of mod_python within this directory. The first is to make changes in the main Apache configuration files. The second is to use a ".htaccess" file within the actual directory. For this test we will initially use the ".htaccess" file as doing so will mean that you will not have to keep restarting Apache each time you make changes to the configuration.
Thus, create a ".htaccess" file in your subdirectory and place in it:
AddHandler python-program .py PythonHandler mptest PythonDebug On
This syntax will work for all versions of mod_python. In version 3.0 and later, the name of the mod_python handler reference has actually been changed and thus it is now preferred to use "mod_python" instead of "python-program". The old name though is still supported and will be used here to avoid confusion for those using version 2.7.
In the same directory create a file called "mptest.py". Use this specific name for the file at this point, do not use any other name. If you insist on not following this advice and use a different name anyway, at least do not call it "test.py" as there is a Python module of the same name. In practice you should avoid using a name which conflicts with any existing Python module as certain configuration mistakes will result in the standard Python module being picked up instead of your own.
In the "mptest.py" file place:
1 from mod_python import apache
2
3 def handler(req):
4 req.log_error('handler')
5 req.content_type = 'text/plain'
6 req.send_http_header()
7 req.write('mptest.py\n')
8 return apache.OK
The call to "send_http_header()" is not actually required if version 3.0 or later of mod_python is being used. If however you are using version 2.7 you should always include this call if you set any of the HTTP response header fields, such as that for content type.
Attempt to access this file using your browser. The last part of the URL should specify "mptest.py". If everything is okay, you should see the string "mptest.py" as the response. At the same time, if you check the Apache error log file you should see that the string 'handler' has been logged to the file.
If instead of the string "mptest.py" you see the actual source code contained in the file, or your browser asks you to save the response to a file and that file contains the source code, the main Apache configuration may not be enabled so as to allow you to specify Apache handlers in a ".htaccess" file. To enable this facility, edit your main Apache configuration file and add in an appropriate location:
<Directory /some/directory> AllowOverride FileInfo </Directory>
Replace "/some/directory" with the absolute pathname to the directory in which the ".htaccess" file is located. You will need to restart Apache before this configuration change takes affect.
If you see neither the correct result, or the source code, but instead the response is a "500 Internal Server Error" response there can be a number of different causes. The first is that you have made a syntax error in your ".htaccess" file. The second is that the directory you created was within a part of the URL namespace managed as CGI scripts and that is taking precedence. This particular problem is sometimes indicated by the error:
Import Error: No module named _apache
Other instances where the response to the request lists a "Mod_python error" and supplies a Python traceback, can indicate that you have managed to make a coding error in the Python code file.
If you receive a "500 Internal Server Error" response and you do not see a Python traceback, it is possible you did not enable the "PythonDebug" option in the configuration. Alternatively, you have hit on one of the obscure cases in mod_python 3.1 and earlier versions where it raises a 500 error but doesn't log the cause of the error.
Whatever the scenario might be for an error response being returned, check the Apache error log file to see if the string 'handler' was logged to the file. If it was, it at least shows that the handler was called. The log file might also contain details of any Python exception and traceback if for some reason this information wasn't returned with the response.
If all is working okay at this point, go back and try again to access the file "hello.txt". This should still work and is because the original configuration specified that any request falling within the directory, as long as it had a ".py" extension, is routed through the content handler defined by "mptest.py". Requests against any other resource using a different extension will be handled by Apache as they normally would.
Global Configuration
To get things started, a ".htaccess" file residing in the same directory as where the content handler was being placed was used. Doing this has the benefits that if needing to make changes to the configuration, it is not necessary to restart Apache as the ".htaccess" file is consulted upon each request.
An additional benefit of using a ".htaccess" file is that it can travel with your files and is under your control. This means you are at slightly less risk of a mistake being made by someone else in the global Apache configuration which changes or deletes your configuration, thus exposing the content of your Python code files along with any other private information.
Being able to use a ".htaccess" file, was however dependent on your directory at least allowing overriding of "FileInfo" aspects of the configuration. If however an Apache administrator will not allow this, you will not have any choice but to have the ability to use mod_python in a directory enabled in the global configuration.
To do this, the exact same configuration as was specified in the ".htaccess" file is used, except that it needs to be surrounded by a "<Directory>" directive. The "<Directory>" directive should be applied to the absolute path name to the directory which contain your files. For example:
<Directory /some/file/system/directory> AddHandler python-program .py PythonHandler mptest PythonDebug On </Directory>
Note that you should not use the "Location" directive as it is not interchangeable with the "Directory" directive within the context of mod_python.
When the "Directory" directive is used, the physical directory referenced will be inserted by mod_python into the Python module search path. This ensures that the module indicated by the "PythonHandler" can actually be found by the Python module importing mechanism if it is located in that directory.
If the "Location" directive is instead used, the path is actually a virtual resource and not a physical directory. As such it cannot be used in the Python module search path. The result will be that mod_python will not be able to find the module implementing the handler as it will not know which physical directory to search for it.
If you have problems with mod_python being able to find your module even when the "Directory" directive is being used, do not be tempted simply to use the "PythonPath" directive to explicitly define its location. If the configuration is setup correctly it should not be required and the use of "PythonPath" can cause more harm than good in complicated systems and thus is best avoided.
If the physical directory you specified for the "Directory" directive isn't located underneath your document root, or isn't otherwise mapped into the URL namespace of your server, you will need to configure Apache to map the directory into an appropriate location. This can be done using the "Alias" directive:
Alias /some/url /some/file/system/directory
Because all the changes described here are being done in the global configuration, Apache will need to be restarted after any change has been made.
Apache Error Log
If having any difficulties with mod_python, it is always a good idea to consult the Apache error log file. The log file is also useful for finding information about Python modules that mod_python is loading.
When starting out with mod_python, the first thing you would want to look for in the error log is evidence that mod_python is actually being loaded by Apache. The startup message of mod_python takes the following form:
[Tue Feb 01 16:08:21 2005] [notice] Apache/2.0.51 (Unix) mod_python/3.1.3 Python/2.3 configured -- resuming normal operations
The first time after a restart that a particular content handler needs to be loaded, mod_python will output a message into the log file to indicate this. The import message for the module containing the content handler will be of the form:
[Tue Feb 01 16:09:32 2005] [notice] mod_python: (Re)importing module 'mptest'
If at any time a content handler raises an unexpected exception for a coding error or other problem, the details will also be recorded in the Apache error log file. If the "PythonDebug" option is not enabled, this will be the only place where the details of an exception in the Python code will be able to be obtained from, as they will not be returned with a response to the browser in that case.
Obtaining Assistance
If after trying everything you are still unable to get even a basic mod_python test handler working, your best course of action is to first consult the mod_python FAQ and the archives of the mod_python mailing list. If you use the search box on the mod_python home page it will search the mailing list archive as well as any other documentation on the mod_python web site.
Failing that, you can subscribe to the mailing list and ask about the problems you are having in that forum. When asking a question, make sure you clearly explain what the problem is and include at least the following information:
- Which version of Python you are using.
- Which operating system platform you are using.
- Which version of mod_python and Apache you are using.
- Whether you are using the global configuration file or a .htaccess file.
- The snippet of the Apache configuration you are using to configure mod_python and enable its use in the directory you are working in.
- Details of any error responses which are being displayed by your web browser.
- Details of messages, be they notices or error messages, which occur in the Apache error log file corresponding to any request you are making which is not working.
- The full contents of the Python code file for the content handler you are trying to use.
The better the information you can provide, the quicker you are likely to get a response. Given that you are seeing this because you have read this document, also make sure you indicate how far you got in following this procedure before things started not working.
