BadPinFactory error when using gpiozero Python library with RaspberryPi 4

I’m trying to run a simple script using the RaspberryPi’s GPIO input.

app.py

from gpiozero import Button

def main():
    button = Button(17)
    button.when_pressed = on_button_press
    button.when_released = on_button_release

def on_button_press():
    print("button 17 pressed!")

def on_button_release():
    print("button 17 released...")

if __name__ == "__main__":
    main()

Dockerfile.template

FROM balenalib/raspberrypi4-64-debian-python:3.11-bullseye-build
WORKDIR /app
RUN pip install RPi.GPIO gpiozero
COPY . .
CMD ["python3", "app.py"]

docker-compose.yml

version: "2"
services:
  app:
    build: .
    environment:
      - GPIOZERO_PIN_FACTORY=RPiGPIO
    privileged: true
    restart: always

I’d really like to be able to use the gpiozero library as I find it much easier to use than RPi.GPIO. However, it seems as though there’s some sort of issue with accessing GPIO factories as when running, I initially got this error:

[app] /usr/lib/python3/dist-packages/gpiozero/devices.py:288: PinFactoryFallback: Falling back from rpigpio: No module named ‘RPi’
[app] warnings.warn(
[app] /usr/lib/python3/dist-packages/gpiozero/devices.py:288: PinFactoryFallback: Falling back from lgpio: No module named ‘lgpio’
[app] warnings.warn(
[app] /usr/lib/python3/dist-packages/gpiozero/devices.py:288: PinFactoryFallback: Falling back from rpio: No module named ‘RPIO’
[app] warnings.warn(
[app] /usr/lib/python3/dist-packages/gpiozero/devices.py:288: PinFactoryFallback: Falling back from pigpio: No module named ‘pigpio’
[app] warnings.warn(
[app] /usr/lib/python3/dist-packages/gpiozero/devices.py:285: NativePinFactoryFallback: Falling back to the experimental pin factory NativeFactory because no other pin factory could be loaded. For best results, install RPi.GPIO or pigpio. See 23. API - Pins — GPIO Zero 1.6.2 Documentation for more information.
[app] warnings.warn(NativePinFactoryFallback(native_fallback_message))

This error happens even with RPi.GPIO installed.

When manually setting gpiozero to use RPi.GPIO as its factory using the GPIOZERO_PIN_FACTORY=RPi.GPIO env variable, I get this error;

gpiozero.exc.BadPinFactory: Unable to find pin factory “RPi.GPIO”

As far as I can tell, this is either a Docker or BalenaOS issue as I’ve not had this problem when running gpiozero natively on Raspberry Pi OS.

Changing the code to use the RPi.GPIO library directly works fine. Given the simple syntax of gpiozero though I’d love the option of using it.

Any help would be much appreciated.

You should be able to get gpiozero running in a container although I haven’t tried it. Here is an example that might help: balena-weather/raingauge at master · hferentschik/balena-weather · GitHub

Hi alanb128,

Thanks for the response.

After reviewing the code you linked there didn’t seem to be any different from what the raingauge.py script was doing compared to the code I provided from a library / package perspective.

One thing I realised I’d left off my app.py code was a way to keep the code from dropping off the end of the main() function.

Updated code:

app.py

from gpiozero import Button
from signal import pause

def main():
    button = Button(17)
    button.when_pressed = on_button_press
    button.when_released = on_button_release
    print(f'{button=}')
    pause()

def on_button_press():
    print("button 17 pressed!")

def on_button_release():
    print("button 17 released...")

if __name__ == "__main__":
    main()

docker-compose.yml

version: "2"
services:
  app:
    build: .
    privileged: true
    restart: always

What’s very odd is that the PinFactory error is now gone! No idea if this is simply related to adding the pause() function call or something else in the backend.

Long story short… issue is solved!

Thanks for confirming that gpiozero should work to motivate me to try things again.