Executing a Python script in Apache2

tpar44 picture tpar44 · Feb 5, 2012 · Viewed 58k times · Source

I am trying to execute a Python program using Apache. However, Apache will only serve the file and not actually execute it. The permissions on the file are r/w/x and it is in /var/www. I will post the contents of httpd.conf and the program code after. I also tried to running the python script as a .cgi file but that did not work as well. I have both the mod_python and mod_wsgi modules loaded into apache as well.

Python sample:

#!/usr/bin/python

# enable debugging
import cgitb
cgitb.enable()

print "Content-Type: text/plain\r\n\r\n"
print

print "Hello World!"

httpd.conf:

AddHandler cgi-script .cgi .pl
AddHandler python-program .py

I know its a small httpd.conf file but when I installed apache, there was nothing in the file. I should also mention that this is just so that I learn the basics of running python in apache. It is not meant for production. Thanks for the help!

Edit

The OS I'm using is Ubuntu 10.04 and the version of apache is 2. I have python version 2.6 which is automatically used when #!/usr/bin/env python is invoked.
I am getting two main errors, the first is that the file is not being found even though the permissions of the file and folder are 777. The error from the log is

[Sun Feb 05 13:29:44 2012] [error] [client 192.168.1.3] File does not exist: /var/www/poit-0.1

This error is for a different python script that I did not write. What is weird is that the file shows up in the index of the folder when accessed from a browser window. However, when I navigate to the file, I get the above error.

The other error that I am getting is premature end of headers. The error is below:

[Sun Feb 05 12:10:19 2012] [error] (8)Exec format error: exec of '/var/www/pyth.py' failed
[Sun Feb 05 12:10:19 2012] [error] [client 192.168.1.3] Premature end of script headers: pyth.py

Answer

b2Wc0EKKOvLPn picture b2Wc0EKKOvLPn · Feb 5, 2012

The first line of httpd.conf: AddHandler cgi-script .cgi .pl is irrelevant, since you're testing python scripts and not perl scripts. And you should define those directives within the location of your python script, and tell apache that it should execute cgi scripts in that location: Options +ExecCGI. This snippet would be a start:

<Directory /path/to/sample.py />
  Options +ExecCGI
  AddHandler cgi-script .py
</Directory>

Addendum 1:

As per my last comment, try this script. It should spit information about the cgi environment.

#!/usr/bin/python
import cgi
cgi.test()

Addendum 2:

I got your script to work with the above configuration. The problem is that script is written in python2. And the default interpreter apache is invoking to execute the script, is python3 (at least in my case, and chances are this would be the same for you too).

This is a python3 version of the hello world script:

#!/usr/bin/env python

# enable debugging
import cgitb
cgitb.enable()

print("Content-Type: text/plain;charset=utf-8")
print()

print("Hello World!")

Addendum 3:

For the first error, make sure the permission and the ownership of whatever directory and files you're attempting to deploy are properly set. And try adding those directives to httpd.conf:

Order allow,deny
Allow from all

Which will get you this:

<Directory /path/to/sample.py />
  Options +ExecCGI
  AddHandler cgi-script .py
  Order allow,deny
  Allow from all
</Directory>

For the second error, unless I am missing something, it looks like apache is invoking python 3 interpreter to execute your script. To rule out this possibility, you might try the following:

ls -al /usr/bin/python*

This will list the python interpreters available on your system. If you have more than one interpreter you'll get something similar to this output:

/usr/bin/python -> python3*
/usr/bin/python2.6*  
/usr/bin/python3*  

If not, it would be this output:

/usr/bin/python -> python2.6*
/usr/bin/python2.6*  

To make sure, this is not the issue you're having, try with this modified sample script:

#!/usr/bin/python2.6

# enable debugging
import cgitb
cgitb.enable()

print "Content-Type: text/plain\r\n\r\n"
print

print "Hello World!"

You'll notice that I explicitly mentioned the version of the interpreter apache should invoke, which is ugly. But for the sake of testing, you can do it. Of course you should map #!/usr/bin/python2.6, to whatever binary you have on your server, and make sure you don't mix python 3 comtipable code with python 2 interpreter and vice versa.