Permission denied: '/sys/class/gpio/gpio2/value'

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Tommy_83
User
Beiträge: 3
Registriert: Sonntag 6. September 2015, 09:49

Hallo,

bin seit kurzem mit einem Raspberry Pi ausgerüstet.
Leider bin ich auf ein Berechtigungsproblem gestossen....

Mit folgender Python-Funktion versuche ich die Werte der GPIO-Pins auszulesen:

Code: Alles auswählen

def getGPIOvalue(gpioPin):
    f = open('/sys/class/gpio/gpio%s/value'%gpioPin, 'r')
    value = f.read() # read value
    f.close()
    return value

def getAllGPIOvalues():
    gpioPin = [2, 3, 4, 14, 15, 18, 17, 27, 22, 23, 24, 10, 9, 11, 25, 8, 7]
    gpioArr = [[0 for x in range(2)] for x in range(len(gpioPin))]

    for i in gpioPin: # loop through all GPIO-Pins
        pinVal = getGPIOvalue(i)
        gpioArr.append([i, pinVal]) # store GPIO-Pin and its value

    return gpioArr
Beim Aufruf von getAllGPIOvalues() kommt folgende Fehlermeldung:

<type 'exceptions.IOError'>: [Errno 13] Permission denied: '/sys/class/gpio/gpio2/value'

Mach ich hier etwas grundsätzlich falsch?
Hab es auch leider nicht geschafft die Berechtigungen entsprechend zu setzen...

Danke für jegliche Hilfe.

Gruß
Benutzeravatar
sparrow
User
Beiträge: 4224
Registriert: Freitag 17. April 2009, 10:28

Entweder musst du die Berechtigungen der Datei anpassen, oder dein Programm mit den entsprechenden Rechten laufen lassen.

Es handelt sich also nicht um ein Problem mit Python, sondern du solltest dich über die Verwaltung und Handhabung von Rechten unter Linux beschäftigen.
BlackJack

@Tommy_83: Der Quelltext sieht auch teilweise nicht nach Python, sondern eher als wenn versucht wurde Code in einer Programmiersprache zu schreiben die keine Namensräume kennt und Arrays mit statischer grösse statt Listen verwendet.

Zur Namensschreibweise wäre ein Blick in den Style Guide for Python Code angeraten.

`gpioArr` ist falsch benannt weil es kein Array ist sondern eine Liste. Aber auch dieser Typ sollte nicht im Namen stehen. Es kommt häufiger vor das man den Typen mal ändert und dann muss man überall im Programm den Namen anpassen oder man hat einen falschen, irreführenden Namen. Die Initialisierung ist auch falsch, denn Du hast da am Ende eine Liste mit ``len(gpioPin)``-Null-Einträgen gefolgt von den tatsächlichen Daten. In Python erzeugt man keine ”leere” Datenstruktur mit Platzhalterwerten um die dann danach der Reihe nach durch die tatsächlichen Werte zu ersetzen, sondern man erstellt eine *tatsächlich* *leere* Liste und hängt dort dann die Werte an. Beziehungsweise kann man in so einfachen Fällen wie diesen mit der „list comprehension“-Syntax (LC-Syntax) auch gleich die Liste mit den Werten erstellen lassen.

Dateien sollte man wo es möglich ist zusammen mit der ``with``-Anweisung öffnen um das schliessen unter allen Umständen sicherzustellen.

Die Kommentare sind allesamt überflüssig weil sie gegenüber dem Quelltext keinen Mehrwert bieten. Wer bei ``value = f.read()`` nicht liest/versteht das dort ein/der Wert gelesen wird, dem wird auch der Kommentar ``# read value`` nicht helfen diese Zeile zu verstehen. Auch die beiden anderen Kommentare enthalten offensichtliche, und damit redundante Aussagen zum dazugehörigen Code.

Ungetestet:

Code: Alles auswählen

VALUE_FILENAME_TEMPLATE = '/sys/class/gpio/gpio{0}/value'
ALL_PINS = [2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27]


def get_value(pin):
    with open(VALUE_FILENAME_TEMPLATE.format(pin)) as value_file:
        return bool(int(value_file.read()))


def get_values(pins=ALL_PINS):
    return [(pin, get_value(pin)) for pin in pins]
Tommy_83
User
Beiträge: 3
Registriert: Sonntag 6. September 2015, 09:49

Danke für eure Hilfe! Dachte mir schon das es ein Rechteproblem ist.

WOW und vielen Dank an BlackJack für die Mühe der ausführlichen Antwort!
Hab schon angefangen den Style-Guide zu lesen.
Tommy_83
User
Beiträge: 3
Registriert: Sonntag 6. September 2015, 09:49

Okay ich musste auch gerade feststellen, dass mein Problem anders ist als beschrieben. Dafür Sorry!

Die Berechtigungen sind folgendermaßen:

Code: Alles auswählen

pi@piV32 ~/python_prog/Webserver/cgi-bin $ ls -la /sys/class/gpio/gpio2/value
-rwxr-xr-x 1 pi root 4096 Sep  7 16:48 /sys/class/gpio/gpio2/value
Das ganze mit dem Code von BlackJack ( Funktionierte auch ungetested einwandfrei :-) )

Code: Alles auswählen

pi@piV32 ~/python_prog/Webserver/cgi-bin $ python gpio.py
[(2, False), (3, False), (4, False), (7, False), (8, False), (9, False), (10, False), (11, False), (14, False), (15, False), (17, False), (18, False), (22, False), (23, False), (24, False), (25, False), (27, False)]
Mein Problem ist, dass ich einen ganz simplen Webserver laufen habe (httpd.py):

Code: Alles auswählen

#!/usr/bin/python

import BaseHTTPServer
import CGIHTTPServer
import cgitb; cgitb.enable()  # This line enables CGI error reporting

server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("", 8000)
handler.cgi_directories = ["/cgi-bin"]
httpd = server(server_address, handler)
print time.asctime(), "Server Starts"
httpd.serve_forever()
Der dann bei dem Aufruf einer index.py über den Webbrowser den Permission-Fehler wirft:

Code: Alles auswählen

import cgi
import cgitb; cgitb.enable()  # for troubleshooting

from gpio import getGPIOvalues

_gpioValues = getGPIOvalues() # list: [Nr, Value]
Hoffe der Kommentar ist diesmal berechtigt...

Fehler:
<type 'exceptions.IOError'>: [Errno 13] Permission denied: '/sys/class/gpio/gpio2/value'

Danke für Hilfe!

Schönen Gruß
BlackJack

@Tommy_83: Da würde ich einen zweiten Server für die GPIO-Sachen schreiben der nur vom lokalen System Anfragen annimmt und den dann vom HTTP-Server aus ansprechen. Denn einen HTTP-Server der von aussen erreichbar ist, möchte man nicht mit root-Rechten laufen haben.
Antworten