Errno 1 Operation not permitted
See original GitHub issueThis may not be an issue with periphery itself, but I’m hoping for some help in diagnosing a problem that currently has me stumped.
If I strip my code down the basics, I end up with the follow, that works:
from periphery import GPIO
import multiprocessing as mproc
from time import sleep
def proc1():
p2=GPIO("/dev/gpiochip0", 2, "in")
p1=GPIO("/dev/gpiochip0", 1, "out")
p1.write(True)
sleep(2)
p1.write(False)
p1.close()
p2.close():
mproc.Process(target=proc).start()
My actual program is more complicated obviously, but at its core I have the same thing happening. A process forked from the main process accessing multiple pins. I can open the pins no problem, I can read all of them no problem, but I get errors when I try to call write
on the GPIO
instance.
Test and program run using sudo python3
so permissions shouldn’t be an issue. I also tried running python3
directly as root using sudo -i
but no change.
I have different results on different hardware, currently I have an RPi3B and an Orange Pi Zero LTS.
- RPi throws err 22 Invalid argument.
- OPi thorws err 1 Operation not permitted.
Any pointers on where to look or how to get more debug information would be most appreciated. For reference, I am working on switching MQTTany over to cdev gpio access and found this library to be the best option. The branch is private, but if you are willing to dig that deep into it, I can publish it.
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (12 by maintainers)
It is actually behaving as you think – the
PermissionError
is getting caught in that except block – but you’re also seeing Python 3’s more thorough chained exception trackback reporting. You can prove to yourself that thePermissionError
is getting caught in the except block by addingprint(e)
orprint(isinstance(e, PermissionError))
before theraise GPIOError(...)
, or by forcing it to cause another knownOSError
, like settingself._line_fd
to a bogus file descriptor, e.g. 99, before thefcntl.ioctl()
, to see that the reporting is similar.As for the reporting, there’s three ways of handling this in Python 3:
Current/do nothing way:
Results in what you’ve seen:
This reports both exceptions involved, but is somewhat confusing as you’ve pointed out, because it seems like two unrelated exceptions occurred.
Explicit exception chaining:
Results in:
This provides the same chained exception context as above, but the reporting is not as confusing as the unlinked version. This is the style I would prefer for Python 3.
Exception suppression:
Results in:
This suppresses the underlying exception, and is probably what you were expecting. This is how Python 2 reports an exception traceback, as exception chaining isn’t available in Python 2.
Unfortunately, since it’s still a goal of python-periphery to support both Python 2 and Python 3 seamlessly, we can’t use the
from e
orfrom None
, as that syntax isn’t available in Python 2. So we have to settle for the slightly confusing reporting under Python 3. Note that it will only be shown when printing a traceback. Programatically, you would just catchGPIOError
as usual.Thank you for the detailed explaination! I was not even aware of that syntax in Python 3. I agree with everything. Too bad Python doesn’t have the dynamic includes you can do with C.