14

I've recently setup python to work with lighttpd via CGI (see here). But the minute I go to include RPi.GPIO, the script stops executing (I'm assuming because no HTML gets output), but there is no error output into the error log (/var/log/lighttpd/error.log).

gpio.py

import RPi.GPIO as GPIO

print "<html>"
print "\t<head>"
print "\t\t<title>GPIO</title>"
print "\t</head>"
print "\t<body>"
print "\t\t<p>"
print "\t\t\tGPIO #17 status: "
print "\t\t</p>"
print "\t</body>"
print "</html>"

Why is the script not executing? Is it because of permissions? Surely, including the library shouldn't require any special permissions? Why isn't there any error output either in the script or in the error log?

Mark Ingram
  • 879
  • 3
  • 11
  • 18
  • This is likely to be one or both of the following permissions/ownership of the included file or the files location. To correct the problem try moving the included file to the same directory as the file you are attempting to run and make sure it is owned by the same user as the script you are running. If this solves the problem let us know and we can direct you further on setting the permissions/ownership and setting the include search path. – Steve Robillard Aug 02 '12 at 19:25
  • I'm a newbie with Python, is RPi.GPIO an actual file (where is it)? \cgi-bin\gpio.py is owned by pi:pi and the permissions for the www directory are www-data:www-data. – Mark Ingram Aug 02 '12 at 19:37
  • OK, a couple of things any file needing to control the GPIO Pins will need to run as root, (which will open a security hole when done via the web). Having said that you will have an easier time debugging any problems if you get the script to work from the command line before trying to get lighttpd and CGI to run as root. To install the RPi.GPIO Module follow these instructions http://learn.adafruit.com/playing-sounds-and-using-buttons-with-raspberry-pi/install-python-module-rpi-dot-gpio. Do you have any electronics experience? What were you going to do with the GPIO pins – Steve Robillard Aug 02 '12 at 19:49
  • I have RPi.GPIO installed already and tested via a command line python script - which works fine. I could understand the whole root thing if I was accessing a pin, but just doing import RPi.GPIO shouldn't rely on permissions should it? – Mark Ingram Aug 02 '12 at 20:02
  • It does if the user the script runs as and the owner of the script differ. Or if the python include path is not accessible by the user running the script. – Steve Robillard Aug 02 '12 at 20:06
  • 1
    Ah, I've just tested this, and a simple script of import RPi.GPIO as GPIO does actually require root privileges! Now I guess I need to get lighttpd to run as root (it's just a home project). – Mark Ingram Aug 02 '12 at 20:08
  • 1
    check this out as an option to running as root http://stackoverflow.com/questions/89228/calling-an-external-command-in-python – Steve Robillard Aug 02 '12 at 20:49
  • Yes, after saying run as root, I realised that I can just use calls to the app "gpio" as part of WiringPi. You can call that without needing root. Trying to get that to work now... – Mark Ingram Aug 02 '12 at 21:04

4 Answers4

6

You may try to add before 'import RPi.GPIO':

import sys 
sys.stderr = sys.stdout
try:
    import RPi.GPIO as GPIO
except Exception as e:
    print e

It may help to diagnose an error.

And add these lines before your html output:

print "Content-Type: text/html"     # HTML is following
print                               # blank line, end of headers

See http://docs.python.org/library/cgi.html

Alex Chamberlain
  • 15,530
  • 14
  • 67
  • 113
okertanov
  • 609
  • 4
  • 2
6

After following the advice from okertanov, I discovered that you can't actually use RPi.GPIO in a python CGI script as it requires root access. I worked around the problem by calling out to the gpio command line app which is included as part of WiringPi, this can be called from a non-root account.

# Read the GPIO pin using the gpio application

import subprocess as s

def ReadGpio(pin) :
    process = s.Popen(["/usr/local/bin/gpio", "-g", "read", pin], stdout = s.PIPE)
    data, _ = process.communicate()

    data = str.replace(data, “\r”, “”)
    data = str.replace(data, “\n”, “”)

    return data
Mark Ingram
  • 879
  • 3
  • 11
  • 18
0

# means a comment in Python

Just use

import RPi.GPIO as GPIO

Now you'll need to solve the permissions problem

John La Rooy
  • 11,947
  • 9
  • 47
  • 75
  • Sorry that was my mistake, I had copied my code which had that line commented out. I've removed it from the original question. – Mark Ingram Aug 03 '12 at 08:49
0

This tutorial recommends creating a special copy of Python and giving it root user privileges, like so:

//check current version
pi@raspberrypi /var/www $ ls -l /usr/bin/python
lrwxrwxrwx 1 root root 9 Jun  6  2012 /usr/bin/python -> python2.7

//copy and chmod
pi@raspberrypi /var/www $ sudo cp /usr/bin/python2.7 /usr/bin/pythonRoot
pi@raspberrypi /var/www $ sudo chmod u+s /usr/bin/pythonRoot

//check that new version has more priveledges
pi@raspberrypi /var/www $ ls -l /usr/bin/pythonRoot
-rwsr-xr-x 1 root root 2674528 Mar 17 18:16 /usr/bin/pythonRoot

And then, to make your CGI, go to sudo nano /etc/lighttpd/lighttpd.conf and find wherever it is you are directing .py files from and change /usr/bin/python/ to the new /usr/bin/pythonRoot/

Seph Reed
  • 311
  • 1
  • 6
  • 17