How-To: Add Python and mod_wsgi to XAMPP

Problems with the Linux version of XAMPP, questions, comments, and anything related.

How-To: Add Python and mod_wsgi to XAMPP

Postby greno » 05. December 2010 01:49

This is a true integration of Python into XAMPP. (Not just using the version of Python found on the OS.)

Backup your current installation:
Code: Select all
cd /opt
sudo tar czf /tmp/xampp-current.tgz lampp


To install Python in XAMPP:
Note: do this in a separate dedicated terminal window since we are setting ENV vars.
Code: Select all
 cd /opt/lampp
 wget http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz
 tar xzf Python-2.7.1.tgz -C /opt/lampp
 cd Python-2.7.1
 ./configure --prefix=/opt/lampp --enable-shared
 export LD_LIBRARY_PATH=/opt/lampp/lib:/usr/lib/:/usr/local/lib:/var/lib
 export LD_RUN_PATH=/opt/lampp/lib:$LD_RUN_PATH
 make   # Note: 2.7.1: got some failures to build:  _tkinter _locale  # I'm probably missing a couple distro packages
 sudo make install


To install mod_wsgi in XAMPP:
Note: mod_wsgi supports Pylons and other WSGI web frameworks
Code: Select all
 cd /opt/lampp
 wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
 tar xzf mod_wsgi-3.3.tar.gz -C /opt/lampp
 cd mod_wsgi-3.3
 ./configure --prefix=/opt/lampp/ --with-apxs=/opt/lampp/bin/apxs --with-python=/opt/lampp/bin/python2.7 --with-mutex-dir=/opt/lampp/var/run/wsgi
 make
 sudo make install


Let's add the proper PATH into Apache:
Code: Select all
sudo echo '                     
PATH="/opt/lampp/sbin:/opt/lampp/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:$PATH"
export PATH' >> /opt/lampp/bin/envvars


Apache /opt/lampp/etc/httpd.conf entries:
Code: Select all
 LoadModule wsgi_module modules/mod_wsgi.so
Include etc/extra/httpd-wsgi.conf

Apache /opt/lampp/etc/extra/httpd-wsgi.conf entries:
Code: Select all
 WSGIPythonHome   /opt/lampp     # XAMPP uses an alternate Python: helps to shield from OS Python Pkg installation under /usr
 WSGISocketPrefix /opt/lampp/var/run/wsgi     # non-standard location acceptable to Apache
 Alias  /media/   /opt/lampp/pylons/mysite/media/      # make sure all Alias come before WSGIScriptAlias
 WSGIScriptAlias  /wsgi-test/    /opt/lampp/var/wsgi/scripts-test/helloworld.wsgi
 <Directory /opt/lampp/var/wsgi/scripts-test>
    WSGIApplicationGroup scripts-test
    Order allow,deny
    Allow from all
 </Directory>


/opt/lampp/var/wsgi/scripts-test/helloworld.wsgi:
Code: Select all
#!/opt/lampp/bin/python
def application(environ, start_response):
    status = '200 OK'
    output = 'Hello World!'

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

    return [output]


Restart Apache
Code: Select all
 /opt/lampp/lampp restartapache


browser to: http://localhost/wsgi-test/helloworld.wsgi

Image

Also check command line
Code: Select all
# /opt/lampp/bin/python
Python 2.7.1 (r271:86832, Dec  4 2010, 01:14:17)
[GCC 4.3.2 20081105 (Red Hat 4.3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/opt/lampp'
>>> sys.path
['', '/opt/lampp/lib/python27.zip', '/opt/lampp/lib/python2.7', '/opt/lampp/lib/python2.7/plat-linux2', '/opt/lampp/lib/python2.7/lib-tk', '/opt/lampp/lib/python2.7/lib-old', '/opt/lampp/lib/python2.7/lib-dynload', '/opt/lampp/lib/python2.7/site-packages']
>>> sys.version
'2.7.1 (r271:86832, Dec  4 2010, 01:14:17) \n[GCC 4.3.2 20081105 (Red Hat 4.3.2-7)]'
>>>


Then let's add a pyinfo() function similar to phpinfo(): ref: http://bran.name (expanded)
(DOCUMENT_ROOT/pyinfo.py)
Code: Select all
import os, sys, platform, cgi, socket

def pyinfo():
    output  = '<!DOCTYPE html>\n'
    output += '<html>'
    output +=  '<head>'
    output +=   '<title>pyinfo()</title>'
    output +=   '<meta name="robots" content="noindex,nofollow,noarchive,nosnippet">'
    output +=    styles()
    output +=  '</head>'
    output +=  '<body>'
    output +=   '<div class="center">'
    output +=     section_title()

    output +=     '<h2>System</h2>'
    output +=     section_system()

    output +=     '<h2>Python Internals</h2>'
    output +=     section_py_internals()

    output +=     '<h2>OS Internals</h2>'
    output +=     section_os_internals()

    output +=     '<h2>WSGI Environment</h2>'
    output +=     section_environ()

    output +=     '<h2>Database support</h2>'
    output +=     section_database()

    output +=     '<h2>Compression and archiving</h2>'
    output +=     section_compression()

    if sys.modules.has_key('ldap'):
        output += '<h2>LDAP support</h2>'
        output += section_ldap()

    if sys.modules.has_key('socket'):
        output += '<h2>Socket</h2>'
        output += section_socket()

    output +=     '<h2>Multimedia support</h2>'
    output +=     section_multimedia()

    output +=     '<h2>Copyright</h2>'
    output +=     section_copyright()

    output +=   '</div>'
    output +=  '</body>'
    output += '</html>'
    return output

def styles():
    css  = '<style type="text/css">'
    css +=  'body{background-color:#fff;color:#000}'
    css +=  'body,td,th,h1,h2{font-family:sans-serif}'
    css +=  'pre{margin:0px;font-family:monospace}'
    css +=  'a:link{color:#009;text-decoration:none;background-color:#fff}'
    css +=  'a:hover{text-decoration:underline}'
    css +=  'table{border-collapse:collapse}'
    css +=  '.center{text-align:center}'
    css +=  '.center table{margin-left:auto;margin-right:auto;text-align:left}'
    css +=  '.center th{text-align:center !important}'
    css +=  'td,th{border:1px solid #999999;font-size:75%;vertical-align:baseline}'
    css +=  'h1{font-size:150%}'
    css +=  'h2{font-size:125%}'
    css +=  '.p{text-align:left}'
    css +=  '.e{width:30%;background-color:#ffffcc;font-weight:bold;color:#000}'
    css +=  '.h{background:url(\'http://python.org/images/header-bg2.png\') repeat-x;font-weight:bold;color:#000}'
    css +=  '.v{background-color:#f2f2f2;color:#000}'
    css +=  '.vr{background-color:#cccccc;text-align:right;color:#000}'
    css +=  'img{float:right;border:0px;}'
    css +=  'hr{width:600px;background-color:#ccc;border:0px;height:1px;color:#000}'
    css += '</style>'
    return css

def table(html):
    return '<table border="0" cellpadding="3" width="600">%s</table><br>' % html

def makecells(data):
    html = ''
    while data:
        html += '<tr><td class="e">%s</td><td class="v">%s</td></tr>' % (data.pop(0), data.pop(0))
    return table(html)

def imported(module):
    if sys.modules.has_key(module):
        return 'enabled'
    return 'disabled'

def section_title():
    html  = '<tr class="h"><td>'
    html +=  '<a href="http://python.org/"><img border="0" src="http://python.org/images/python-logo.gif"></a>'
    html +=  '<h1 class="p">Python %s</h1>' % platform.python_version()
    html += '</td></tr>'
    return table(html)

def section_system():
    data = []
    if platform.dist()[0] != '' and platform.dist()[1] != '':
        data += 'OS Version', '%s %s (%s %s)' % (platform.system(), platform.release(), platform.dist()[0].capitalize(), platform.dist()[1])
    else:
        data += 'OS Version', '%s %s' % (platform.system(), platform.release())
    if hasattr(os, 'path'): data += 'OS Path', os.environ['PATH']
    if hasattr(sys, 'version'): data += 'Python Version', ''.join(sys.version)
    if hasattr(sys, 'subversion'): data += 'Python Subversion', ', '.join(sys.subversion)
    if hasattr(sys, 'prefix'): data += 'Python Prefix', sys.prefix
    if hasattr(sys, 'path'): data += 'Python Path', sys.path
    if hasattr(sys, 'executable'): data += 'Python Executable', sys.executable
    data += 'Build Date', platform.python_build()[1]
    data += 'Compiler', platform.python_compiler()
    if hasattr(sys, 'api_version'): data += 'Python API', sys.api_version
    return makecells(data)

def section_py_internals():
    data = []
    if hasattr(sys, 'builtin_module_names'):
        data += 'Built-in Modules', ', '.join(sys.builtin_module_names)
    data += 'Byte Order', sys.byteorder + ' endian'
    if hasattr(sys, 'getcheckinterval'):
        data += 'Check Interval', sys.getcheckinterval()
    if hasattr(sys, 'getfilesystemencoding'):
        data += 'File System Encoding', sys.getfilesystemencoding()
    data += 'Maximum Integer Size', str(sys.maxint) + ' (%s)' % str(hex(sys.maxint)).upper().replace("X", "x")
    if hasattr(sys, 'getrecursionlimit'):
        data += 'Maximum Recursion Depth', sys.getrecursionlimit()
    if hasattr(sys, 'tracebacklimit'):
        tabdatale += 'Maximum Traceback Limit', sys.tracebacklimit
    else:
        data += 'Maximum Traceback Limit', '1000'
    data += 'Maximum Unicode Code Point', sys.maxunicode
    return makecells(data)

def section_os_internals():
    data = []
    if hasattr(os, 'getcwd'):     data += 'Current Working Directory', os.getcwd()
    if hasattr(os, 'getegid'):    data += 'Effective Group ID', os.getegid()
    if hasattr(os, 'geteuid'):    data += 'Effective User ID', os.geteuid()
    if hasattr(os, 'getgid'):     data += 'Group ID', os.getgid()
    if hasattr(os, 'getgroups'):  data += 'Group Membership', ', '.join(map(str, os.getgroups()))
    if hasattr(os, 'linesep'):    data += 'Line Seperator', repr(os.linesep)[1:-1]
    if hasattr(os, 'getloadavg'): data += 'Load Average', ', '.join(map(str, map(lambda x: round(x, 2), os.getloadavg())))
    if hasattr(os, 'pathsep'):    data += 'Path Seperator', os.pathsep
    try:
        if hasattr(os, 'getpid') and hasattr(os, 'getppid'):
            data += 'Process ID', ('%s (parent: %s)' % (os.getpid(), os.getppid()))
    except: pass
    if hasattr(os, 'getuid'): data += 'User ID', os.getuid()
    return makecells(data)

def section_environ():
    envvars = os.environ.keys()
    envvars.sort()
    data = []
    for envvar in envvars:
        data += envvar, cgi.escape(str(os.environ[envvar]))
    return makecells(data)

def section_database():
    data  = []
    data += 'DB2/Informix (ibm_db)',      imported('ibm_db')
    data += 'MSSQL (adodbapi)',           imported('adodbapi')
    data += 'MySQL (MySQL-Python)',       imported('MySQLdb')
    data += 'ODBC (mxODBC)',              imported('mxODBC')
    data += 'Oracle (cx_Oracle)',         imported('cx_Oracle')
    data += 'PostgreSQL (PyGreSQL)',      imported('pgdb')
    data += 'Python Data Objects (PyDO)', imported('PyDO')
    data += 'SAP DB (sapdbapi)',          imported('sapdbapi')
    data += 'SQLite3',                    imported('sqlite3')
    return makecells(data)

def section_compression():
    data  = []
    data += 'Bzip2 Support', imported('bz2')
    data += 'Gzip Support',  imported('gzip')
    data += 'Tar Support',   imported('tarfile')
    data += 'Zip Support',   imported('zipfile')
    data += 'Zlib Support',  imported('zlib')
    return makecells(data)

def section_ldap():
    data = []
    data += 'Python-LDAP Version' % urls['Python-LDAP'], ldap.__version__
    data += 'API Version',                               ldap.API_VERSION
    data += 'Default Protocol Version',                  ldap.VERSION
    data += 'Minimum Protocol Version',                  ldap.VERSION_MIN
    data += 'Maximum Protocol Version',                  ldap.VERSION_MAX
    data += 'SASL Support (Cyrus-SASL)',                 ldap.SASL_AVAIL
    data += 'TLS Support (OpenSSL)',                     ldap.TLS_AVAIL
    data += 'Vendor Version',                            ldap.VENDOR_VERSION
    return makecells(data)

def section_socket():
    data  = []
    data += 'Hostname', socket.gethostname()
    data += 'Hostname (fully qualified)', socket.gethostbyaddr(socket.gethostname())[0]
    try:
        data += 'IP Address', socket.gethostbyname(socket.gethostname())
    except: pass
    data += 'IPv6 Support', getattr(socket, 'has_ipv6', False)
    data += 'SSL Support', hasattr(socket, 'ssl')
    return makecells(data)

def section_multimedia():
    data  = []
    data += 'AIFF Support',                    imported('aifc')
    data += 'Color System Conversion Support', imported('colorsys')
    data += 'curses Support',                  imported('curses')
    data += 'IFF Chunk Support',               imported('chunk')
    data += 'Image Header Support',            imported('imghdr')
    data += 'OSS Audio Device Support',        imported('ossaudiodev')
    data += 'Raw Audio Support',               imported('audioop')
    data += 'Raw Image Support',               imported('imageop')
    data += 'SGI RGB Support',                 imported('rgbimg')
    data += 'Sound Header Support',            imported('sndhdr')
    data += 'Sun Audio Device Support',        imported('sunaudiodev')
    data += 'Sun AU Support',                  imported('sunau')
    data += 'Wave Support',                    imported('wave')
    return makecells(data)

def section_copyright():
    html = '<tr class="v"><td>%s</td></tr>' % sys.copyright.replace('\n\n', '<br>').replace('\r\n', '<br />').replace('(c)', '&copy;')
    return table(html)

optional_modules_list = [
    'Cookie',
    'zlib', 'gzip', 'bz2', 'zipfile', 'tarfile',
    'ldap',
    'socket',
    'audioop', 'curses', 'imageop', 'aifc', 'sunau', 'wave', 'chunk', 'colorsys', 'rgbimg', 'imghdr', 'sndhdr', 'ossaudiodev', 'sunaudiodev',
    'adodbapi', 'cx_Oracle', 'ibm_db', 'mxODBC', 'MySQLdb', 'pgdb', 'PyDO', 'sapdbapi', 'sqlite3'
]
for i in optional_modules_list:
    try:
        module = __import__(i)
        sys.modules[i] = module
        globals()[i] = module
    except: pass


/opt/lampp/var/wsgi/scripts-test/pyinfo.wsgi:
Code: Select all
#!/usr/bin/env python
import os,sys
def application(environ, start_response):
    path = environ['DOCUMENT_ROOT']
    if path not in sys.path:
        sys.path.append(path)
    from pyinfo import pyinfo
    output = pyinfo()
    start_response('200 OK', [('Content-type', 'text/html')])
    return [output]


browser to: http://localhost/wsgi-test/pyinfo.wsgi

Image




Enjoy.

-Gerry


.
greno
 
Posts: 54
Joined: 04. October 2006 19:25

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby amit.var » 23. August 2011 10:10

Nice post..

I got another link too which is also good and simple -
http://tek-insight.blogspot.com/2011/06/setting-up-modwsgi-for-python-in-web.html

NOTE: This link points to a WINDOWS Python/XAMPP integration, not a Linux one
JonB - AF Moderator
amit.var
 
Posts: 1
Joined: 23. August 2011 10:08

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby kaege » 17. October 2011 09:52

When I do
Code: Select all
./configure --prefix=/opt/lampp/ --with-apxs=/opt/lampp/bin/apxs --with-python=/opt/lampp/bin/python2.7 --with-mutex-dir=/opt

the teminal said
Code: Select all
checking Apache version... cannot open /opt/lampp/build/config_vars.mk: No such file or directory at /opt/lampp/bin/apxs line 217.
cannot open /opt/lampp/build/config_vars.mk: No such file or directory at /opt/lampp/bin/apxs line 217.
cannot open /opt/lampp/build/config_vars.mk: No such file or directory at /opt/lampp/bin/apxs line 217.
./configure: line 1708: /: Is a directory

cannot open /opt/lampp/build/config_vars.mk: No such file or directory at /opt/lampp/bin/apxs line 217.
configure: creating ./config.status
config.status: error: cannot find input file: Makefile.in

What should I do?
kaege
 
Posts: 2
Joined: 23. July 2011 08:20

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby JonB » 17. October 2011 13:16

Shortly after you decide to share what LAMPP version you are working with, we can get on to addressing your question -

Then of course the question(s) will be --

Well - where did you derive the syntax for that??? And what did you think would occur???

Did you attempt the method given by the OP (greno) ???

That would be a good starting place.

Good Luck
8)
User avatar
JonB
AF Moderator
 
Posts: 3210
Joined: 12. April 2010 16:41
Location: Land of the Blazing Sun
XAMPP Version: 1.8.3-2
Operating System: Windows XP/7 - Fedora 15 1.7.7

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby ananefri » 29. May 2012 14:16

hi..how if python is already installed but not connected? I am newbie, help me please. Thank you.

-Ana
ananefri
 
Posts: 1
Joined: 29. May 2012 14:11
XAMPP Version: 5.6.3
Operating System: LINUX

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby JonB » 30. May 2012 05:27

Although I have not tested it, I am reasonably sure you can execute Python scripts just like Perl scripts; i.e. as CGI scripts (meaning no need for Apache mod_wsgi -- which is an Apache module like mod_perl, which allows the interpreter (Perl or Python) to be called as an extension of Apache). CGI is a protocol that dates back to the beginnings of Web scripting and is still in use with other server side tools and languages. Its common with Perl and with compiled C++.

Read though this - it details what is needed, along with the 'shebang' convention (just like Perl). Using CGI means that you will be actually running an executable on your server, so it 'usually' means that the script has to reside in 'cgi-bin' (a specially configured directory tree that is NOT in the DocumentRoot).

http://www.penzilla.net/tutorials/python/cgi/

and an explantaion of CGI

http://en.wikipedia.org/wiki/Common_Gateway_Interface

Good Luck
8)
User avatar
JonB
AF Moderator
 
Posts: 3210
Joined: 12. April 2010 16:41
Location: Land of the Blazing Sun
XAMPP Version: 1.8.3-2
Operating System: Windows XP/7 - Fedora 15 1.7.7

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby ackt1c » 28. July 2012 11:35

well i get this
httpd: Syntax error on line 123 of /opt/lampp/etc/httpd.conf: Cannot load /opt/lampp/modules/mod_wsgi.so into server: /opt/lampp/modules/mod_wsgi.so: wrong ELF class: ELFCLASS64

i've tryed alot
mod_wsgi3.X(4) on python3.2 with apache 2.4 in xampp1.8.0 /w devel
mod_wsgi3.3 on python2.7 with apache 2.2 in xampp1.7.7 /w devel
i also compiled mod_wsgi3.3 with CFLAGS = -Wc,-fno-stack-protector to bypass stack-smashing as described at -> http://code.google.com/p/modwsgi/wiki/InstallationIssues

i even copied the wsgi3.3-3-x86_64 i got with the packager but the symlinks were all wrong
nothing really comes up as an answer

btw installing mod_wsgi and apache2.2 by the packager works, but xampp just fails to initiate Apache.
any help would be great

edit:
i also got
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
ImportError: No module named site

plus:
XAMPP is currently only availably as 32 bit application. Please use a 32 bit compatibility library for your system.

this thread should be deleted as mod_wgsi and python are only compiled 64 bit
unless i'm wrong? all i can come up with is the xampp packaged apache is compiled as 32 bit and leaving mod_wsgi.so incompatible, or by using gcc-multilib to start xampp i somehow compiled python/mod_wsgi incorrectly, or my symlinks are incorrect

none the less i'm discouraged to install all these packages that xampp offers individually, i really like xampp and maybe in the future apache python mod_wsgi postgresql and phppgadmin could be packaged in 64 bit? or am i way outta line?

thanks
Sincerely,
Joey
ackt1c
 
Posts: 1
Joined: 28. July 2012 11:32
XAMPP Version: 5.6.3
Operating System: Linux-3.4.6-1-ARCH-x86_64

Re: How-To: Add Python and mod_wsgi to XAMPP

Postby JonB » 28. July 2012 15:17

Joey -

Most of what you are saying is pretty accurate, and reflects how hard you worked on it. The 'real obstacle' is that, because XAMPP/LAMPP does not really 'install itself' the way a "LAMP" stack normally would, its almost impossible to 're-compile' Apache.

And it does not matter if you built a LAMP stack by one-at-a-time 'hand-compiles' and installation, or by using repositories (.rpm, .deb, etc) and installers (yum, apt-get and so forth) - the result would be the same either 'you' or the installer would resolve all the dependencies abd get everything it the 'right place' so the other parts would know where to find the required support. I have already tried to fix GD and other libraries both for XAMPP on Windows and on Linux - not happening.

It would be possible with enormous patience and knowledge, to do a correct 'make' for almost any module you wanted. Of course, if you knew all the configure requirements that well you would not need XAMPP, right??? :mrgreen: All you actually need is the correct source, and a complete knowledge of Apache and the GCC 'compiler'...

I do have some good news - adding Python to XAMPP has already been discussed several times, and I think there is a willingness to do that (via mod-wsgi). On the other hand, AFAIK, You can currently build python by itself, and 'point' to it (as in perl). It is a general-purpose language, and should work correctly under the CGI model. Se my post 'two up' - "should work" :D

These projects are driven by tiny teams, all volunteers, who are at the mercy of the 'source projects' issues (bugs), scheduling of releases and 'stalling'. Look at all the versions XAMPP went though last year (and yeppers) - there's a maintenance release of Apache looming at the moment (ditto phpMyAdmin).

Thanks for working on it and reporting your efforts.

BUT JonB is not going to delete/lock this, as Alladin may arrive at any moment and rub the magic 'lampp' - " 'Pooof' and a powerful python emerged from the bottle"

Good Luck
8)
User avatar
JonB
AF Moderator
 
Posts: 3210
Joined: 12. April 2010 16:41
Location: Land of the Blazing Sun
XAMPP Version: 1.8.3-2
Operating System: Windows XP/7 - Fedora 15 1.7.7


Return to XAMPP for Linux

Who is online

Users browsing this forum: No registered users and 2 guests