RIP。美しく響く歌声でした。これからの作品を楽しみにしていましたが、25歳とは早すぎて胸が痛い。
Python 3のコレクションの抽象基底クラス
時々、dict風の動作をする自前クラスを作りたくなることがあるが、何を満たせばdict風になるのか毎回調べていたので、ここにメモしておく。 と言っても、ドキュメントに全てまとまっているので、以下を参照するだけ。
抽象基底クラスについては、PEP 3119で提案がある。
ここで、以下のサンプルコードを実行してdict
とMutableMapping
のクラス階層を表示してみる。
import collections.abc from typing import * def print_class_hierarchy(t: Type, depth: int = 0): print(''.join(' ' for _ in range(depth)) + t.__name__ + ' (' + t.__class__.__name__ + ')') if t != object: for base_type in t.__bases__: print_class_hierarchy(base_type, depth+1) print_class_hierarchy(dict) print() print_class_hierarchy(collections.abc.MutableMapping) print() print(issubclass(dict, collections.abc.MutableMapping))
出力結果は以下のようになる。
dict (type) object (type) MutableMapping (ABCMeta) Mapping (ABCMeta) Collection (ABCMeta) Sized (ABCMeta) object (type) Iterable (ABCMeta) object (type) Container (ABCMeta) object (type) True
出力結果より、dict
とMutableMapping
はクラス階層的には継承関係にはないことが読み取れるが、issubclass(dict, MutableMapping)
はTrue
になる。
これは、PEP 3119の提案によると、issubclass()
をオーバーライドして、あたかもdict
がMutableMapping
のサブクラスであるかのように見せかけているためである。
言語のコアな部分を変更せずに、コレクションの性質を抽象化する工夫と思われる。
最後に蛇足だが、もうちょっと広くPythonのデータモデル (というより型モデル) はこちらを参照。
2013/10/15追記。 各クラスのメソッドも表示するようにして、継承関係のツリーの罫線も引いてみた。
import inspect import collections.abc from typing import * def print_class_hierarchy(node: Union[Type, str], indent_types: list[str] = []) -> None: indents = '' for index, indent_type in enumerate(indent_types): indent = '??????' # this value must be never used if index != len(indent_types) - 1: if indent_type == 'TYPE': indent = ' | ' elif indent_type == 'TYPE_LAST': indent = ' ' else: if indent_type == 'METHOD': indent = ' | ' elif indent_type == 'METHOD_LAST': indent = ' ' elif indent_type == 'TYPE': indent = ' +-- ' elif indent_type == 'TYPE_LAST': indent = ' `-- ' indents = indents + indent node_text = (node.__name__ + ' (' + node.__class__.__name__ + ')') if isinstance(node, Type) else node print(indents + node_text) if isinstance(node, Type): base_types = list(node.__bases__) methods = {member for member, _ in inspect.getmembers(node, inspect.isfunction)} base_methods = {member for base_class in node.__bases__ for member, _ in inspect.getmembers(base_class, inspect.isfunction)} indent_type = 'METHOD' if len(base_types) > 0 else 'METHOD_LAST' for method in list(methods - base_methods): print_class_hierarchy(method, indent_types + [indent_type]) if node != object: for index, base_type in enumerate(base_types): indent_type = 'TYPE' if index != len(base_types) - 1 else 'TYPE_LAST' print_class_hierarchy(base_type, indent_types + [indent_type]) print_class_hierarchy(collections.abc.MutableMapping)
出力結果は以下。
MutableMapping (ABCMeta) | setdefault | __setitem__ | pop | clear | popitem | __delitem__ | update `-- Mapping (ABCMeta) | items | get | values | keys | __eq__ | __getitem__ `-- Collection (ABCMeta) +-- Sized (ABCMeta) | | __len__ | `-- object (type) +-- Iterable (ABCMeta) | | __iter__ | `-- object (type) `-- Container (ABCMeta) | __contains__ `-- object (type)
Power BIで「データをモデルに読み込み中」で止まる現象の解決方法
問題
クリーンインストールしたWindows 11に、ここからPower BIをダウンロードしてインストール。 しかし、Excelファイルに接続してデータを読み込もうとすると、以下のポップアップが表示されて処理が進まない。
解決方法
キャッシュをクリアすると解決する可能性がある。 メニューから「ファイル」=>「オプションと設定」=>「オプション」を選択する。
そして以下のように、一通りボタン「キャッシュをクリア」を押下する。
参考
Shift JIS (というかCP932)のCSVを扱うPythonプログラムを、VS Codeで開発するための作業テンプレ
- はじめに
- 環境
- Pythonで利用するツールやライブラリ
- (1) Poetryのインストール
- (2) プロジェクトの作成
- (3) コードの作成
- (4) Pandasのインストール
- (5) VS Codeで仮想環境を指定
- (6) 動作確認
はじめに
レガシーな業務系の基幹システムとデータ連携する場合は、まだまだCSVが活躍している。 今後もCSV処理ツールを作り続けそうなので、作業のテンプレを残しておく。
特に注意が必要なのが、日本語版のWindowsで作成されたCSVは、往々にして文字コードがCP932であるところ。
環境
$ cat /etc/os-release | grep PRETTY_NAME PRETTY_NAME="Ubuntu 22.04.2 LTS" $ uname -srvm Linux 5.19.0-40-generic #41~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 31 16:00:14 UTC 2 x86_64 $ python3 --version Python 3.10.6 $ code --version 1.77.3 704ed70d4fd1c6bd6342c436f1ede30d1cff4710 x64
Pythonで利用するツールやライブラリ
今回のPythonプログラムの開発では、以下を利用する。
(1) Poetryのインストール
Poetryの公式サイトの手順に沿って、以下のコマンドを実行する。
$ curl -sSL https://install.python-poetry.org | python3 -
以下のように、Poetryのバージョンを確認してみる。
$ poetry --version Poetry (version 1.4.2)
(2) プロジェクトの作成
ここでは、作成するプロジェクトの名前をcsvsample
とする。
以下のように、ターミナルでプロジェクトを作成するディレクトリ(例えば~/src
)に移動した後、プロジェクトを作成する。
$ cd ~/src $ poetry new csvsample
その結果、以下のようなディレクトリ構成が作成される。
~/src └── csvsample ├── README.md ├── csvsample │ └── __init__.py ├── pyproject.toml └── tests └── __init__.py
(3) コードの作成
まず、~/src/csvsample
をワーキングディレクトリとしてVS Codeを起動した後、Explorerでcsvsample/tool.py
を作成し、以下の内容で保存する。
import sys import pandas def main(csv_file_path): data_frame = pandas.read_csv(csv_file_path, encoding='cp932') print(data_frame) if __name__ == '__main__': main(sys.argv[1])
pandas.read_csv()
に引き渡す文字コードだが、「WindowsはShift JIS」という思い込みがあるので思わず'shit_jis'
を指定したくなるものの、これだと機種依存文字に対応できない場合がある。
よって、Shift JISのMicrosoftの拡張である'cp932'
が正解。
この時点では、まだPandasがインストールされていないので、コードエディタ上でimport pandas
あたりがエラーになっているはず。
次に、以下の内容でdata.csv
を作成しておく。
"id","name","age" "1000","John","20" "1001","Jane","30"
(4) Pandasのインストール
ライブラリPandasをインストールするために、Terminalを開いて以下のコマンドを実行する。
$ poetry add pandas
Pandasをインストールしても、まだコード中のエラーは消えないはず。
(5) VS Codeで仮想環境を指定
コード中のpandasが見つからないというエラーを解消するには、VS CodeにPoetryが作成した仮想環境を指定する必要がある。
Poetryは、デフォルトでは~/.cache/pypoetry/virtualenvs
に仮想環境のディレクトリを作成する。
VS Codeのcommand palletでpython: select interpreter
と入力するか、ステータスバーの以下の部分をクリックして、Pythonの仮想環境を指定するポップアップを開く。
そして、以下のように右端にPoetryと書いてあるエントリを選択する。
これで、コードエディタ上のエラーは解消する。
(6) 動作確認
VS Code上のTerminalを開き直すと、上記で設定した仮想環境に自動的に切り替わる。 そのTerminalで以下のように作成したPythonプログラムを実行する。
$ python3 csvsample/tool.py data.csv id name age 0 1000 John 20 1 1001 Jane 30
Ubuntu 22.04LTSでゲームパッドが認識されない場合の対処
はじめに
ThundeRobot社製のゲームパッドを利用しているが、PCを買い替えたら認識されなくなった。 対処方法を調べたので、メモしておく。
環境
$ cat /etc/os-release | grep PRETTY_NAME PRETTY_NAME="Ubuntu 22.04.2 LTS" $ uname -srvm Linux 5.19.0-40-generic #41~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 31 16:00:14 UTC 2 x86_64
対処方法
ググってなんとか対処方法が書いてある以下に辿り着いた。
投稿を信じるなら、カーネル 5.16以降で発生する事象のようなので、自分の環境は該当する。
コメントで言及されているworkaround通りに/etc/modprobe.d/nonintendo.conf
を以下の内容で作成してリブートすると、認識された。
blacklist hid_nintendo
対処前後のsudo lshw
の結果を比較すると、差分は以下のように出た。
まずは対処前。
詳細: ヒューマンインターフェースデバイス(HID) 製品: THUNDEROBOT G30 ベンダー: Nintendo Co., Ltd 物理ID: 1 バス情報: usb@1:1 バージョン: 1.15 性能: usb-2.00 設定: driver=usbhid maxpower=500mA speed=12Mbit/s *-usb:1
次に対処後。
詳細: 汎用USBデバイス 製品: Microsoft X-Box 360 pad ベンダー: Microsoft Corp. 物理ID: 1 バス情報: usb@1:1 論理名: input44 論理名: /dev/input/event22 論理名: /dev/input/js0 バージョン: 1.15 シリアル: 12340000 性能: usb-2.00 usb 設定: driver=xpad maxpower=500mA speed=12Mbit/s *-usb:1
対処前はNintendoのプロダクトとして、対処後はMicrosoftのプロダクトとして認識されている。
対処前は/dev/input/
にマッピングされずに困っていたが、対処後はマッピングできていることが分かる。
参考
snapでインストールしたThunderbirdのメッセージフィルタのコピー
はじめに
Thunderbirdでメールフィルタを別のアカウントにコピーしたかったが、画面上からコピーするメニューが見当たらなかった。 調べたところ、メールフィルタの設定はテキストファイルとしてThunderbirdのプロファイルのディレクトリの中に配置されており、単なるファイルコピーで別のアカウントにコピーできるようだ。
しかし、snapでインストールしたThunderbirdだとsnap固有の場所にプロファイルがあり、その場所はググっても見つけにくかったので、ここでメモしておく。
プロファイルの場所
snapでインストールしたThunderbirdのプロファイルは以下の場所にある。
~/snap/thunderbird/common/.thunderbird/[ランダム文字列].default
[ランダム文字列]
は以下で確認できる。
$ cat ~/snap/thunderbird/common/.thunderbird/profiles.ini [Profile0] Name=default IsRelative=1 Path=[ランダム文字列].default Default=1 [General] StartWithLastProfile=1 Version=2
メールフィルタのコピー
以下のように、アカウント1
にメールフィルタの設定ファイルmsgFilterRules.dat
があるとして、
/path/to/[ランダム文字列].default └── Mail ├── アカウント1 │ └── msgFilterRules.dat └── アカウント2
単にこの設定ファイルをアカウント2
にコピーして、以下のようにすればよい。
/path/to/[ランダム文字列].default └── Mail ├── アカウント1 │ └── msgFilterRules.dat └── アカウント2 └── msgFilterRules.dat
MySQLのroot@localhostのパスワード設定
はじめに
とあるサンプルプログラムを実行することになったのだが、MySQLへの接続にアカウントがroot@localhostを利用し、なおかつabc123のようなパスワードで接続するようになっていた。 サンプルのあちこちにMySQLへのログインのコードがあるので、サンプルに合わせてMySQLのroot@localhostのパスワードを変更することにした。 そこで少し詰まったので、作業メモを残しておく。
作業メモ
初期状態のrootは、パスワードでのログインではなく、UNIXソケットを利用したログインになっているようだ。 普通にクライアントであるmysqlを実行すると、ソケットへのアクセス権がないためかログインに失敗するので、sudoで実行する。
$ sudo mysql -u root
ログインできたら、MySQLのユーザのログインの方式を確認してみる。
mysql> select user, host, plugin from mysql.user; +------------------+-----------+-----------------------+ | user | host | plugin | +------------------+-----------+-----------------------+ | debian-sys-maint | localhost | caching_sha2_password | | mysql.infoschema | localhost | caching_sha2_password | | mysql.session | localhost | caching_sha2_password | | mysql.sys | localhost | caching_sha2_password | | root | localhost | auth_socket | +------------------+-----------+-----------------------+ 5 rows in set (0.00 sec)
確かに、rootはUNIXソケット経由でのログインになっていそうだ。 そのため、他のユーザと同様にパスワードでのログインに変更する。
mysql> update mysql.user set plugin = 'caching_sha2_password' where user = 'root'; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> flush privileges;
そして、rootのパスワードを設定しておく。
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'abc123'; Query OK, 0 rows affected (0.01 sec) mysql> flush privileges;
mysqlコマンドを終了して、次はパスワード認証を実施してみる。
mysql> quit; $ mysql -u root -p
これでログインできていれば成功となる。
補足
ユーザ権限を特定の方法で変更した場合にflush privilegesを実行する必要があるそうだ。 実行タイミングまで調べきれていないので、とりあえず上記では認証方式の変更後とパスワード変更後に呼び出している。