Armadilloフォーラム

Alpine:3.22でpythonのlibgpiod2ライブラリを使用する方法

k.sato

2025年8月28日 14時39分

==========
ABOSバージョン:3.21.3-at.12
カーネルバージョン:5.10.237-0-at
その他:コンテナ:alpine 3.22
==========

お世話になっております。
佐藤と申します。

今まで自作コンテナをalpine:3.20で開発していて、alpine:3.22に上げたところ
gpiodの初期化のところでエラーとなってしまいました。

gpio4 = gpiod.Chip('/dev/gpiochip3')
disp_in = gpiod.get_line(gpio4, 9)
AttributeError: module 'gpiod' has no attribute 'get_line'
 
gpio4 = gpiod.Chip('/dev/gpiochip3')
disp_in = gpio4.get_line(9)
AttributeError: 'Chip' object has no attribute 'get_line'. Did you mean: 'get_info'?
 
gpio4 = gpiod.Chip('/dev/gpiochip3')
disp_in.request(consumer='foo', direction=gpiod.Line.Direction.INPUT)
disp_in = gpio4.request_lines(
	config=gpiod.RequestConfig(consumer='foo', event_buffer_size=0),
	settings={9: set_input}
)
AttributeError: module 'gpiod' has no attribute 'RequestConfig'

gpiodはswuを作成するときにpackages.txtにpy3-libgpiodを追記してインストールしています。

armadillo:~# podman exec -it my_project sh
/ # pip list | grep gpiod
gpiod          2.2.0

正しい記述方法を教えていただけませんか?

以上、よろしくお願い致します。

コメント

at_shota.shimoyama

2025年8月28日 19時11分

アットマークテクノの下山です。

バージョンが2.0.2以降のgpiodはそれより前との互換性が無くなりました。
また、alpine 3.21 から apkで提供されるgpiodのバージョンは2.2以降になりました。

そのため、alpine 3.20 から 3.22 になったことによってgpiodの後方互換性がなくなり、エラーが表示されています。

新たな記述方法は以下のサイトに記載されています。

https://libgpiod.readthedocs.io/en/latest/python_api.html

https://github.com/brgl/libgpiod/tree/master/bindings/python

今回の場合、例えば次のように記載することでエラーを回避できるはずです。

import gpiod
from gpiod.line import Direction
 
def read_gpio():
    with gpiod.request_lines(
        '/dev/gpiochip3',
        consumer="my-app",
        config={9: gpiod.LineSettings(direction=Direction.INPUT)},
    ) as request:
        value = request.get_value(9)
        print(f'GPIO 9 = {value}')
        return value
 
read_gpio()

よろしくお願いします

下山様

佐藤です。
回答ありがとうございます。

> https://libgpiod.readthedocs.io/en/latest/python_api.html
>
> https://github.com/brgl/libgpiod/tree/master/bindings/python

> 今回の場合、例えば次のように記載することでエラーを回避できるはずです。

> import gpiod
> from gpiod.line import Direction
> 
> def read_gpio():
>     with gpiod.request_lines(
>         '/dev/gpiochip3',
>         consumer="my-app",
>         config={9: gpiod.LineSettings(direction=Direction.INPUT)},
>     ) as request:
>         value = request.get_value(9)
>         print(f'GPIO 9 = {value}')
>         return value
> 
> read_gpio()

上記を参考にreadの確認はできました。

https://github.com/brgl/libgpiod/tree/master/bindings/python

import time
 
from gpiod.line import Direction, Value
 
LINE = 5
 
with gpiod.request_lines(
    "/dev/gpiochip0",
    consumer="blink-example",
    config={
        LINE: gpiod.LineSettings(
            direction=Direction.OUTPUT, output_value=Value.ACTIVE
        )
    },
) as request:
    while True:
        request.set_value(LINE, Value.ACTIVE)
        time.sleep(1)
        request.set_value(LINE, Value.INACTIVE)
        time.sleep(1)

上記を参考に下記を作成してみたのですが、
これでは毎回GPIOの初期化をしてからの出力H/Lセットとなっているようです。

import time
import gpiod
from gpiod.line import Direction, Value
 
#緑LEDピンNo
LED_G = 25
 
# GPIO出力セット
def set_gpio(line, value):
	with gpiod.request_lines(
		'/dev/gpiochip2',
		consumer="my-app",
		config={line: gpiod.LineSettings(direction=Direction.OUTPUT)},
	) as request:
		act = Value.ACTIVE if value else Value.ACTIVE
		request.set_value(line, act)
 
# 緑LEDの出力セット
set_gpio(LED_G, 1)

先頭でGPIOの初期設定を行い、
以降ではrequest.set_valueを使い回すような書き方は出来るのでしょうか?

以上、よろしくお願い致します。

佐藤です。

連投スミマセン
下記のようにすればよいですね。

LED_G = 25
g_led_g = None
 
def init_gpio(line)
	global g_led_g
 
	g_led_g = gpiod.request_lines(
		'/dev/gpiochip2',
		consumer="my-app",
		config={line: gpiod.LineSettings(direction=Direction.OUTPUT)},
	)
 
 
g_led_g .set_value(LED_G, Value.ACTIVE)

以上、よろしくお願い致します。

at_shota.shimoyama

2025年8月29日 13時01分

はい、それでも問題ないはずです

withステートメントを使用していた理由としては、withステートメントを抜けるときに自動的にGPIOのlineの占有をリリース(gpioinfoで見えるconsumer=my-appの表示が消える)してくれるからです(おそらくwithステートメントを抜けるときに自動的にrequest.release()を呼び出してくれる)
こうすることで、(このpythonスクリプトがそのwithステートメントにいるタイミングを除いて)他のプログラムからも同じlineを使用できます

ただ、このpython以外にGPIOの同じlineを使用するプログラムなどがないのであれば、自動的にリリースする必要はないためg_led_g = gpiod.request_lines(...)としても問題ないと思います

もしリリースする必要がある場合には後から g_led_g.release()を呼び出す必要があると思います

よろしくお願いします