WPP
LM22 (Ubuntu 24.04) で pyrealsense2 をセットアップするためにしたあれこれ

結論からいうと pyenv で python 3.11 入れれば OK。

LM22 (Ubuntu 24.04相当) には、python 3.12 が入っていて pyrealsense2 を pip でインストールできなかったので、当初仕方なくビルドしました。

ビルドには成功しましたが、自分の知識では pipenv 環境下に配置することができずに結局は pyenv で python3.11 をインストールし pip しました。
pipenv 環境下でビルドすると仮想環境の lib に make インストールすることになるようでインストールした pyrealsense2 を pipenv から認識することができませんでした。

ビルドの方法はこんな感じ、必要に応じて -dev パッケージは追加してください。

$ git clone 
$ sudo apt install libssl-dev
$ sudo apt-get install libglfw3-dev 
$ sudo apt install  libudev-dev
$ sudo apt install libusb-dev- libusb-1.0-0-dev


$ git clone https://github.com/IntelRealSense/librealsense.git realsense
$ cd realsense
$ git checkout v.2.56.2
$ mkdir build
$ cd build
$ cmake ../ -DBUILD_PYTHON_BINDINGS:bool=true -DBUILD_EXAMPLES:bool=true -DBUILD_PYTHON_DOCS=true

$ make -j4

pythonサンプルは [cloneしたフォルダ]/wrappers/python/examples の中に入っている。

冒頭にも書いている通り pyenv で python 3.11 をインストールした。というのも LM22 (多分 Ubuntu 24.04 も) Python 3.12 以下のバージョンのパッケージは用意されていないので apt でインストールできない。
なので、pyenv を使って以下の手順で回避した。(もちろん pyenv でなくてもいい)

$ curl https://pyenv.run | bash
$ pyenv local 3.11
$ pipenv shell
$ pipenv install pyrealsense2

; エラーがでなければインストールに成功している。
$ python 
Python 3.11.10 (main, Oct 24 2024, 17:33:16) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyrealsense2
>>> 

誤って .python-version を消さないようにしなくちゃ。

参考

librealsense/wrappers/python at master · IntelRealSense/librealsense

KivyMD の NavigationDrawer に RecycleView を追加するサンプル

引き続き、Kivy です。

今回は、KivyMD の NavigationDrawer の中に RecycleView を突っ込んでみます。Kivy / KivyMD はここのコンポーネントを動作確認する分には特別難しいことはありませんが、複数組み合わせるとトタンになかなかいい感じに配置することができないのが難点だと思う。(自分の理解の浅さのせいかもしれないが、HTML/CSS の方がまだましに感じます。)

提示するサンプルを実行するとこんな感じになります。前回と同じように Appbar が画面上部にあり、 Appbar のアイコンを押すと、NavigationDrawer が表示されます。その NavigationDrawer の中に 果物の名前のリストを表示しています。

Appbar のアイコンが左で、ドロワーが右から出てくるのは違和感があるかもしれませんが anchor の確認のためにあえて行っています。

環境

  • Kivy 2.3.0
  • KivyMD 2.0.1.dev

コード

from kivy.lang import Builder

from kivy.properties import StringProperty

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.recycleview import MDRecycleView


KV = '''
MDScreen:

    MDNavigationLayout:
        # size_hint_x: 1

        ScreenManager:
            MDScreen:

                MDBoxLayout:
                    md_bg_color: self.theme_cls.secondaryContainerColor
                    orientation:'vertical'
                    
                    MDTopAppBar:                        
                        MDTopAppBarLeadingButtonContainer:
                            MDActionTopAppBarButton:
                                icon: 'menu'
                                on_release: nav_drawer.set_state('toggle')
                            
                        MDTopAppBarTitle:
                            text: 'this is AppBar'
                            pos_hint: {'center_x': .5}
                            
                    MDLabel:
                        text: "I'm MDLabel"

        MDNavigationDrawer:
            anchor: 'right'

            MDBoxLayout:
                orientation: 'vertical'

                MDNavigationDrawerLabel:
                    text: 'drawer items!!'
                    icon: 'format-list-bulleted'

                MDNavigationDrawerDivider:

                NvDrawerRecycleItem:                    
                    id: rv
                    padding: 0, nav_drawer.height, 0, 0
                    viewclass: 'Food'
                    RecycleBoxLayout:
                        size_hint: (1, None)
                        height: self.minimum_height
                        orientation:'vertical'

<NvDrawerRecycleItem>:

<Food>:
    text: 'name: {}'.format(self.item)
    adaptive_size: True
    padding: 0, dp(16), 0, dp(16)

'''

class Food(MDLabel):
    item = StringProperty('')

class NvDrawerRecycleItem(MDRecycleView):
    pass


class TestNavigationDrawer(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    
    def on_start(self):
        rv = self.root.ids.rv
        rv.data = (
            { 'item': it }
            for it in [
                'Apple', 'Banana', 'Cherry', 'Grape', 'Lemon',
                'Mikan', 'Orange', 'Pear', 'Lychee', 'Strawberry',
                'Peach', 'Fig'
            ]
        )


TestNavigationDrawer().run()

公式のサンプルでは MDNavigationDrawerMenu の中に Drawer の中身を入れてるのですが、そうすると RecycleView と MDNavigationDrawerMenu の間に大きな隙間ができてしまい。どうしても制御することができませんでした。

また、MDBoxLayout: orientation: ‘vertical’ で囲ってあげないと ドロワー系のアイテムと RecycleView が横並びになってしまいました。

そのため、上のようなサンプルコードになりました。


        MDNavigationDrawer:
            id: nav_drawer
            anchor: 'right'

            MDBoxLayout:
                orientation: 'vertical'

                MDNavigationDrawerMenul:
                    MDNavigationDrawerLabel:
                       text: 'drawer items!!'
                       icon: 'format-list-bulleted'

                      MDNavigationDrawerDivider:

                NvDrawerRecycleItem:                    
                    id: rv
                    padding: 0, nav_drawer.height, 0, 0
                    viewclass: 'Food'
                    RecycleBoxLayout:
                        size_hint: (1, None)
                        height: self.minimum_height
                        orientation:'vertical'

今作りたいものをやるのにドロワーの中にリスト入れればいけるんじゃね?と安直に考えてやってみたがなかなかしんどかった。Kivy の道はきびしい。

KivyMD の Appbar 画面上部にピッタリに配置する方法

さあ、今日も Kivy の話です。

KivyMD にはあたかも Android アプリのような Appbar というコンポーネントがあります。これを画面のトップに配置して下部分に大きさピッタリのコンテンツを配置する方法のメモです。

やりたいことは、2つあります。

  1. Appbar を画面トップに配置する。
  2. 空いた下の領域いっぱいにコンテンツを表示する。

結果はこんな感じになります。

画像を入れる

環境

  • Kivy 2.3.0
  • KivyMD 2.0.1.dev

最終的なサンプル

from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
MDScreen:
    MDBoxLayout:
        orientation: 'vertical'
        padding: 0,app_bar.height, 0,0      # L T R B

        MDBoxLayout:
            md_bg_color: 0.2,0.2,0.4, 1
            MDLabel:
                text: 'text label'
                valign: 'bottom'

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        
        MDTopAppBarLeadingButtonContainer:
            MDActionTopAppBarButton:
                icon: 'menu'
                
        MDTopAppBarTitle:
            text: 'top appbar'
        
        MDTopAppBarTrailingButtonContainer:
            MDActionTopAppBarButton:
                icon: "github"
'''

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    
if __name__ == '__main__':
    MainApp().run()

画面トップに配置

自分が試した限りでは、 TopAppBar を公式サンプルのまま配置しただけでは画面の上部に表示することはできませんでした。(これバグ何じゃないだろうか ?)

なので pos_hint に ‘top’: 1 を設定してやります。kivy では画面左下が原点になるので ‘top’: 1 は画面の最上部を意味します。(0 – 1.0 が入り割合を示すらしい。)

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        

コンテンツを Appbar の下ギリギリまで配置する

次に、コンテンツ領域の制御です。ここはなにも制限しないと親の大きさいっぱいまで使ってしまいます。つまりコンテンツ領域が Appbar で隠れるか、 Appbar を隠すかしてしまいます。(これは .KV 内の定義の順番によるっぽいです。)

Stack overflow で見つけた解決策は padding を設定して下の領域の大きさを明示的に制限するというものでした。こんな感じです。

padding に設定してやるのは Appbar の高さなので id: 属性を追加します。

追加した id (Appbar) の高さ分 padding でコンテンツ領域を下げてやります。

    MDBoxLayout:
        orientation: 'vertical'
        padding: 0,app_bar.height, 0,0      # Left Top Right Bottom

   # いろいろ省略

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        # size_hint_x: 1

Kivy / KivyMD は配置周りの挙動がよくわからないのが辛い。

参考

python – How do i make an MDBottomAppBar appear on top of a list view in KivyMD – Stack Overflow

Appbar — KivyMD 2.0.1.dev0 documentation

Kivy AnchorLayout が効かない時はサイズを指定すると良い

今回も Kivy ネタです。

下記のようなコードで(コメントアウトは除き) で右寄せが効かずちょいハマりました。

Stack Overflow にスレがあり、CSS のブロックエレメント/インラインエレメント のような感じでMDLabel の幅が max に設定されてしまうようです。

コメントアウトを解除すると無事に右寄せが機能しました。

Label を MDLabel にすると別のスタイルが有効になるようで文字が見切れてしまいます。その場合は size を texture_size から変更する必要があるようです。ここは追求していません。

from kivy.lang import Builder
from kivymd.app import MDApp

KV = '''
MDScreen:
    MDBoxLayout:
        orientation: 'vertical'
        
        AnchorLayout:
            # size_hint_x: 1
            anchor_x: 'right'
            anchor_y: 'center'
    
            Label:
                text: 'menu-'

                # この2行を追加すれば OK
                # size_hint: (None, None)
                # size: self.texture_size
                max_lines: 1                    
                padding: (dp(16), dp(0))
'''

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    

if __name__ == '__main__':
    MainApp().run()

参考

python – Kivy AnchorLayout .Kv file – Stack Overflow

Kivy のログレベル変更

さて、今日も Kivy です。 Kivy 戦記ってブログがあるんですが、Kivy をやってる時はまさに「戦い」って感じでいちいち面倒くさいです。

Kivy をコンソールから実行するとログが流れてきます。そのログレベルを変更しようと思います。
というのも、.kv ファイルの記述どおりにどうも動かない現象にぶち当たりましたがデフォルトのログレベルではなにも異常はなさそうだったのでもう少し詳しく見る必要がありました。

どうやら Kivy.config にコンフィグ設定値があるようです。
ログレベルに限らず、Config は環境変数で渡せるようですが、設定ファイルを使ってみます。

自分の環境ではそもそも設定ファイルは、存在しませんでした。おそらくそれが普通のようです。Config のドキュメントから設定値読み取っていちいち手入力するのはだるいなと思っていたら、ファイルに書き出す機能がありました。

$ python -m kivy
>>> from kivy.config import Config as cfg
>>> cfg.write()

こうすると ~/.kivy/config.ini が生成されているはずです。Win/Mac もそれっぽいところにあります。

それはそうと config.ini を書き換えていきます。log 周りの設定だけでなくデフォルトフォントの設定など色々ありそうですが、今回はつかわないので log_level を debug に変更します。

info や debug 以外にもドキュメントにある通り warn, error, trace なんかも設定できるようです。

[kivy]
..... いろいと並んでいる
log_dir =
log_enable =1
log_level = debug
....

にしても Kivy の API (クラス) リファレンスは、キーワードと説明の区別がつけにくくて読み取りにくいのがどうも好きになれない。

参考

Configure Kivy — Kivy 2.3.0 documentation

Configuration object — Kivy 2.3.0 documentation

pipenv で setup.py のパッケージをインストールする方法

pipenv の仮想環境で setup.py をインストールする方法です。

KivyMD の最新を git から持ってくると setup.py でのインストールを求められますが、やり方を知らなかったのでメモします。

pipenv の公式に載っているのですが run pip install すればいいらしい。

$ pipenv run pip install -e .

ちなみに、git で取ってきた KivyMD の example を動作させるには、プロジェクトのルートで python example/xxx.py のように実行するか、PYTHONPATH に追加する必要がある。インストールしても仮想環境にコピーされないので注意。

ついでに requirements.txt でインストールする場合は以下のようになる

$ pipenv install -r ./requirements.txt

参考

pipenv · PyPI

kivymd/KivyMD: KivyMD is a collection of Material Design compliant widgets for use with Kivy

pip search の代替

pip search が廃止されて結構長いこと時間が経っているが、いい感じの代替が見つかったのでメモする。

pypi に pypi-search というのが登録されていたので試してみた。

2024-12-24 追記: pypi-search で検索できなくなった。

2024-9-3 追記: pipx でインストールすることにした

pypi-search インストール

// pipenv 内で実行していたので pipx に変更する
//$ pip install pypi-search
$ pipx install pypi-search
$ pipy-search mqtt
[INFO] :: Searching for package `mqqt`...
[INFO] :: Could not find package `mqqt`
[INFO] :: Searching for other packages that match that query...

Here are some packages that match `mqqt`:
=========================================================================================================================================================================================================================

Name         : dyrkdevice
Version      : 0.1.0
Release date : Oct 24, 2021
Description  : Library for implementing a dyrk device

$ $ pypi-search -help
usage: pypi-search [-h] [-d] [--version] [-o] search

Search for PyPi packages

positional arguments:
  search             Package to show information on

options:
  -h, --help         show this help message and exit
  -d, --description  Show package description
  --version          show program's version number and exit
  -o, --open         Open homepage in browser

これでいちいち pypi をブラウザで開く必要がなくなりそうで助かるなと。

Ubuntu 24.04 かそれに含まれる Python 3.12.3 は pip が venv の中でしか実行できないらしい。先日インストールできたのははからずも、venv 内で作業していたため後日 pypi-search を実行できないことに気がついた。pipx なら実行できるらしい。

python 製のコマンドツールはちょくちょくあるので pipx でインストールするようにしよう。恐らく pip –user と同じようなことをしているのだと思われる。

pypi-search のエラー 12/24 追記

今日の時点で実行するとこんなエラーが起きている

$ pypi-search  numpy
[INFO] :: Searching for package `numpy`...
Traceback (most recent call last):
  File "/home/mnishi/.local/bin/pypi-search", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/mnishi/.local/share/pipx/venvs/pypi-search/lib/python3.12/site-packages/pypi_search/main.py", line 35, in main
    version_info = pypi.get_version_info()
                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mnishi/.local/share/pipx/venvs/pypi-search/lib/python3.12/site-packages/pypi_search/utils.py", line 41, in get_version_info
    version_no = package_name_header.text.split()[1]
                 ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'text'

ソース見てみると .local/share/pipx/venvs/pypi-search/lib/python3.12/site-packages/pypi-search の utils.py で URL を開いている。(package_name は、検索したい文字列)

ここで .text が返ってこないらしい。

        self.response: Optional[requests.Response] = requests.get(
            f'http://pypi.org/project/{self.package_name}'
        )
        try:

試しに、wget するとエラーを意味する html が返ってきてよく見ると javascript が動かないとだめってことらしい。恐らく以前からのスクレーピング対策が強化されたようだ。

それもあるのか、pypi-search の Github に行くとアーカイブになっていた。javascript 対応するのが面倒なのでもうやめることにしたのだと思う。

うーん、困った。

[参考]

【備忘録】Ubuntu 24.04 で Python3.12 の Pip を利用する #Linux – Qiita

俺流!PEP668とうまくやっていく方法 | スクエニ ITエンジニア ブログ

pipenv の仮想環境をカレントに作る

よくあるネタですが、自分が探しやすいようにメモります。

ここのところ python の仮想環境は pipenv に落ち着いているのですが (venv 使っていた頃より余計な作業が減った気がする)、賛否両論ありますがカレントのプロジェクトフォルダにつくる方法です。

# 一時的に環境変数を経由
$ export PIPENV_VENV_IN_PROJECT=1
$ pipenv shell

# .env 設定ファイルを介して行う方法
$ echo ""PIPENV_VENV_IN_PROJECT=1" >> .env
$ pipenv shell

いちいち忘れるので .env の雛形ファイルを作って雛形フォルダに置いておいた。

これで大丈夫だろう

Linux Mint 21.3 Virginia の pipenv でエラー + Python バージョンを切り替えられるようにする

python の開発環境は pipenv を使っているのですが、Linux Mint の標準リポジトリに入っている pipenv だとエラーになって動かない。

入っている Python は 3.10 。ネットを検索してみると pipenv が古いとかなんとか。。。一旦消して pip でインストールし直すのがいいらしいのでやってみた。

$ sudo apt install pipenv-

# python3 しかはいっていないので pip3 とする必要はない pip で OK
$ pip install pipenv

これで解決。

ついでに Python バージョンを切り替えられるようにしておく。pyenv でもいいのですが、今回は update-alternatives にします。というのもこの辺のツールの移り変わり早いので廃れるとわりと放置されがち、ちょっと時間経つと面倒なことになる印象があります。

update-alternatives なら Ubuntu 系の OS では他のコマンド切り替えるためにも使われているっぽいのでだいじょぶそうじゃないかと。。。

# 末尾が優先度で多きい方が優先らしい
$ sudo update-alternatives --install /usr/bin/python python3 /usr/bin/python3.10 110
$ sudo update-alternatives --install /usr/bin/python python3 /usr/bin/python3.11 100

# リストが出てくるので [selection] の数字を選ぶと切り替わる
$ sudo update-alternatives --config python

参考

Ubuntu 22.04にPython3.xを複数インストールして切り替える方法(PPA・apt) #Python – Qiita