summaryrefslogtreecommitdiff
path: root/docs/user-guides/assorted-tips-and-tricks.rst
blob: 6fb54b5ed0d4ee449e32f33c7a75f8a8318ad4e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
========================
Assorted Tips And Tricks
========================

This document contains various tips and tricks related to using mod_wsgi
which don't deserve a document of their own or which don't fit within other
documentation.

Determining If Running Under mod_wsgi
-------------------------------------

As a WSGI application developer you should always be striving to write
portable WSGI applications. That is, you should not write your code so as
to be dependent on the specific features of a specific WSGI hosting
mechanism.

This unfortunately is not always possible especially when it comes to
deployment due to there being no one blessed way for exposing a WSGI
application for hooking into WSGI hosting mechanisms. There may also be
times when you might want to rely on a feature of a specific WSGI hosting
mechanism, which although not part of the WSGI specification, allows you
to do something you wouldn't otherwise.

That said, there a few ways in which you can detect that your code is
running under mod_wsgi. These fall under two categories. The first being
a general mechanism for how to detect if mod_wsgi is being used. The
second being additional ways to detect that mod_wsgi is being used when a
request is being handled.

The simplest way of detecting if mod_wsgi is being used is to import the
'mod_wsgi' module. This is a special embedded mode which is installed
automatically by the Apache/mod_wsgi module into set of imported modules,
ie., sys.modules. You can thus do::

    try:
        import mod_wsgi
        # Put code here which should only run when mod_wsgi is being used.
    except:
        pass

Do note however that although this is an embedded mode added automatically,
the way mod_wsgi has been implemented allows in the future for there to be
a separate Python package/module distinct from the mod_wsgi.so file called
'mod_wsgi' which might contain additional Python code to support use of
mod_wsgi.

What would happen if such a separate Python package/module is available is
that it will be automatically imported and additional information setup by
the Apache/mod_wsgi module then inserted into the global namespace of that
Python package/module.

The potential existance of this distinct Python package/module means that
importing 'mod_wsgi' could one day actually succeed outside of code being
run under the Apache/mod_wsgi module.

A more correct test therefore is::

    try:
        from mod_wsgi import version
        # Put code here which should only run when mod_wsgi is being used.
    except:
        pass

This is different because the 'version' attribute will only be present when
running under the Apache/mod_wsgi module as that version relates to the
version of mod_wsgi.so.

The above import check can be used anywhere, be that in the WSGI script file,
or in your application code at either global scope or within the context of
a specific function.

In the specific case of the WSGI script file, although the above can be
used there is an alternate check that can be made. That is to check the
value of the '__name__' attribute given to the WSGI script file when the
code is loaded into the Python interpreter.

The normal situation where one would check the value of '__name__' is where
wanting to do something different when a Python code file is executed
directly against the Python interpreter as opposed to being imported. For
example::

    if __name__ == '__main__':
        ...

In contrast, were a Python code file is imported, the '__name__' attribute
would be the dotted path which would be used to import the code file.

In the case of mod_wsgi, although WSGI script files are imported as if they
are a module, because they could exist anywhere and not in locations on
the Python module search path, they don't have a conventional dotted path
name. Instead they have a magic name built from a md5 hash of the path to the
WSGI script file.

So as to at least identify this as being related to mod_wsgi, it has the
prefix '_mod_wsgi_'. This means a WSGI script file could use::

    if __name__.startswith('_mod_wsgi_'):
        ...

if it needed to execute different code based on whether the WSGI script
file was actually being loaded by the Apache/mod_wsgi module as opposed to
be executed directly as a script by the command line Python interpreter.

This latter technique obviously only works in the WSGI script file and not
elsewhere.

A final method that can be used within the context of the WSGI application
handling the request is to interrogate the WSGI environ dictionary passed
to the WSGI application. In this case code can look for the presence of
the 'mod_wsgi.version' key within the WSGI environ dictionary::

    def application(environ, start_response):
        status = '200 OK'
        if environ.has_key('mod_wsgi.version'):
            output = 'Hello mod_wsgi!'
        else:
            output = 'Hello other WSGI hosting mechanism!'

        response_headers = [('Content-type', 'text/plain'),
                            ('Content-Length', str(len(output)))]
        start_response(status, response_headers)

        return [output]