How to configure PyWX

The main installation and configuration information for PyWX can be found in the INSTALL file in the distribution. This page contains some discussion of higher-level considerations regarding the configuration of PyWX.

PyWX invocation

There are two ways for PyWX to be invoked: through a mapping to a C++ handler function that calls a Python function that sources your .py script, or as a filter that runs a Tcl function that in turns runs a Python function that sources the script. If you are interested, you can read about the gory details of the two procedures. However, once your script is running, there is hardly a difference between the two methods.

This option is configured by using either the Map directive in your configuration file, or setting "EnablePythonPages On" in the config file and installing 00-python.tcl in your tcl directory. See the INSTALL file for more information.

Interpreter reuse

Should Python interpreters be recycled after a connection is done and used again for other connections, or should a brand-new interpreter be created for each connection? This behavior is configured via the ReuseInterpreters option. More details about Python's execution environments are available here.

In neither case do multiple Python scripts run at the same time in the same interpreter. That would require multiple threads within a single Python interpreter, which hasn't been implemented yet.

Reusing interpreters has a significant speed advantage, mostly (it seems) because Python modules only need to be initialized once in each interpreter. However, reused interpreters provide slightly less isolation between scripts, and might be more prone to memory leaks due to buggy scripts.

Attaching standard input and standard output

The canonical and most efficient way to return headers and content to the client with AOLserver is via AOLserver API calls, of which there is a huge variety. In PyWX, these functions are available as member functions of the Ns.Conn connection object such as conn.SetHeaders(), conn.ReturnHtml(), conn.ReturnData(), and conn.Redirect().

However, PyWX also provides a method to return headers and content by printing them to sys.stdout in the same format that is used by CGI scripts. Internally, sys.stdout is attached to a special object called a PyWX_buffer which: parses the headers and sets them via the above API; and buffers the content then gives it all at once to AOLserver. This method is obviously less efficient than using the API calls directly, but it may be more convenient, especially if you are already familiar with CGI programming.

The choice of whether to attach a PyWX_buffer object to sys.stdin and sys.stdout is configured with the AttachStdio option in the configuration file.

Emulating a CGI environment

Aside from special treatment of stdin and stdout, a CGI script requires additional special settings in its environment. Information about the request needs to be set in environment variables; the working directory needs to be changed to the directory containing the script; and other information must be put in the script's command-line arguments. None of this is strictly necessary for a PyWX script, because the same information is available via the AOLserver API.

However, since many people already have scripts written to the CGI standard, PyWX provides a way to emulate the CGI environment to allow old CGI scripts to take advantage of the huge performance gain of running in a multithreaded server. The emulation is necessarily imperfect, though, because things like the current working directory are shared by all threads in a process and so can't be changed without affecting all scripts. Moreover, turning on CGI emulation causes a memory leak in the current version (0.6) of PyWX.

To turn on CGI emulation, enable the SetupCGIEnv option in your configuration file.

Caching compiled scripts

Normally your Python scripts are run by PyWX using Python's execfile() function. execfile() has two undesirable features from a performance point of view: it reads the file each time from disk, and it doesn't even compile the file into a .pyc bytecode file (as is done with imported Python modules) so it has to parse the file anew each time. To avoid these problems, PyWX can use a specially-written replacement version of execfile() that caches the compiled code in memory the first time a script is run, and thereafter runs the precompiled code. (If the modification time of the file on disk has changed, it reloads the file.) This feature can be enabled or disabled by setting the variable UseCachingExec in the file pywx.py. In the future we might provide a configuration-file option to set this parameter.

The disadvantages of caching compiled scripts are that cached scripts permanently consume server memory, and that the implementation is currently not thread-safe. The performance advantage depends heavily on the application; if you run short scripts that load most of their code from modules, it shouldn't make much difference. But if you use long scripts, the gain might be substantial.

If you want the caching execfile() to override the normal execfile() within your scripts too, set InstallCachingExec in the same file.