This document discusses some of the common pitfalls in getting python scripts running under Windows, with an emphasis on enabling python cgi scripts through Windows Apache.
Most programs won't run from the DOS command line unless you specify the full path to their executables. When running python scripts on Windows, you'd really like to be able to just type python my_script.py from the directory where your script lives, instead of having to explain exactly where the python interpreter is located. To enable this behavior, you'll need to add the python install directory to the Path environment variable on your machine; this variable is a list of directories that Windows will automatically seach through to find an executable named python.
The following instructions are for Windows 2000, but should at least give you an idea of where to start on other versions. (Note that you can only alter environment variables if you are logged in as the machine's administrator.) Right-click on the desktop icon for your machine (captioned My Computer, if you haven't renamed it) and go to Properties. This pops up a dialogue box of system information; click on the Advanced tab and then on the Environment Variables button. In the new dialogue that pops up, click on the Path variable in the System Variables box; then click the Edit button.
Place your cursor in the Variable Value textbox, right before the final double-quote of the string. Type a semicolon (to separate the previous value from the one you're about to add) and then type the location of the python executable on your system-- probably something like C:\Python . Click OK until you're out of all the dialogue boxes. Now, when you type python at any DOS command prompt, Windows will be able to automatically find and run the correct executable.
Now that you've taught Windows to find the python executable in the python install directory, you'll need to tell it how to find your python scripts saved in folders other than that one; otherwise, your python import statements will fail because they won't know where to look for the custom modules you wish to import. Possible module locations are specified by the PYTHONPATH environment variable, which is stored in the Windows registry.
To augment PYTHONPATH, run regedit and navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore and then select the folder for the python version you wish to use. Inside this is a folder labelled PythonPath, with one entry that specifies the paths where the default install stores modules. Right-click on PythonPath and choose to create a new key. You may want to name the key after the project whose module locations it will specify; this way, you can easily compartmentalize and track your path modifications.
Your new key will have one string value entry, named (Default). Right-click on it and modify its value data; this should be text in the same format as the Path environment variable discussed above--absolute directory paths, separated by semicolons. If one project will use modules from several directories, add them all to this list. (Don't bother attempting to add more string value entries to your new key, or to the original PythonPath key, since they will be ignored.) Once these new registry entries are in place, your scripts' import statements should work fine.
I won't discuss installing Apache; apache.org offers good instructions for Windows users. You will almost certainly want to follow the directions for setting up Apache as a service (rather than a console application), since it provides maximum up-time and convenience.
Recent Apache installations for Windows locate all configuration instructions in the httpd.conf file. On the web, you may encounter older directions that tell you to modify the contents of other files like access.conf or srm.conf--don't. You can (and should) do it all in httpd.conf. Also, to make life easier for beginners, httpd.conf already contains most of the directives (Apache commands) that you could ever need, written in as comments. To enable them, just delete the comment character # at the beginning of their lines.
In spite of these efforts to simplify, administering Apache is still an arcane and confusing art. Don't be afraid to add your own comments to the httpd.conf file indicating what you changed and why; just as with code, you'll thank yourself later. I strongly recommend that you add your this file to your source control system. This will allow you to (a) back up to a working version should you screw it up, and (b) keep a running record of what you changed to get a particular feature working--very useful should you ever need to enable that functionality on a different install.
In order to convince Apache to run your python CGI scripts, you will need to ensure that a few directives are in place in httpd.conf. Often, directives are grouped by the directories they apply to, inside <Directory> tags. The default document root (public html) directory on Windows Apache installs is /apache/htdocs, although this can be changed (in httpd.conf, of course!) Assuming you have not changed it, look for the following line:
A few lines below this is one that begins with the word Options and is followed by a whitespace-separated list of terms. Make sure that ExecCGI is included in this list of terms; this will ensure that pages Apache serves are allowed to call CGI scripts.
Now look down the file and find the line reading <IfModule mod_mime.c>. A great many directives are included if this module is present, but down among the list you should see a few lines beginning with the term AddHandler. Uncomment (or add, if a commented version doesn't exist) the following one:
AddHandler cgi-script .py
Voila! Now Apache knows that .py files can be CGI scripts, and that your pages are allowed to run them.
The first line of a cgi script is the shebang line, which indicates the location of the program that should be used to interpret the script. If your cgi scripts will be run ONLY on Windows, you can use Windows-specific shebang lines, which look something like this:
Note the -u following the interpreter path; this is very important. It puts the python interpreter in "unbuffered" mode. Trying to run python cgi scripts in the (default) buffered mode will either result in a complete lack of return value from your cgi script (manifesting as a blank html page) or a "premature end of script headers" error.
Of course, the shebang line above cannot be used on a *nix system (or even a Windows system where python is installed at a different location.) There are several ways around this; for instance, you can work out a hack based on the fact that Apache interprets shebang paths as relative to the drive root if no drive letter is provided, and assumes an .exe extension if none is included in the path. Thus, #!/usr/bin/env python is interpreted as looking for env python.exe (remember that Windows filenames can contain spaces) in c:/usr/bin. The -u flag is missing here, but unbuffered behavior can be restored with a little tweak to the httpd.conf file (see below).
But wait! There's a better way. Apache has anticipated this issue, and provided a directive to handle it. Open your httpd.conf file and uncomment the line that reads
This instructs Apache to completely ignore the shebang line. Instead, it will examine the Windows registry to find the program associated with the script's file extension (.py), and use that program as the interpreter. You are now free to include *nix style shebang lines in your scripts in the sure knowledge that Windows Apache will not try to read them. Even better, your code can now be moved to a different Windows box on which python is installed in some nonstandard directory; as long as the box's registry reflects that location, your scripts will run with no changes.
What about the buffering mode, though? No Windows-style shebang line means no -u switch. Httpd.conf to the rescue again. Add the lines
in your http.conf file. Env instructions set or retrieve environment variables of the shell from which a script is called; these variables are then passed on to the script itself. The first instruction passes the PYTHONPATH variable (see the discussion of setting this variable for Windows above) to the script. The second sets the PYTHONUNBUFFERED environment variable to 1 (true) and then passes it to the script, creating the desired -u behavior by an alternate means.
© Amanda Birmingham 2004