DataClass 3.10での機能追加(kw_only, slots)
こんにちはPython界のレアキャラです。
dataclassから機能が追加され attrsであった機能が取り込まれました。 以前書いた記事のアップデートをしておこうと思います。
TL;DR
- dataclassにkw_onlyと slotsが入った
- attrsのつかいどころ
- ボイラープレートコードを避けたい.(特にdataclassにない機能を利用したい)
- 今Python3.9 以下を使っているし、今後dataclassを使いたい.
- ドキュメントをきちんと読むと色々書いてある
kw_only
https://docs.python.org/ja/3.10/glossary.html#term-parameter キーワード専用フィールドを設定するためのもの.
>>> # クラスの全フィールドをキーワード専用にするもの >>> @dataclass(kw_only=True) ... class A: ... a: int ... b:int ... >>> a = A(1,2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: A.__init__() takes 1 positional argument but 3 were given >>> a = A(a=1,b=2) >>> a A(a=1, b=2)
ちなみに1フィールドだけ キーワード専用にしたいときは dataclasses.field
でできる。
>>> from dataclasses import field >>> @dataclass ... class B: ... x:int ... y:int = field(kw_only=True) ... >>> B(1,2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: B.__init__() takes 2 positional arguments but 3 were given >>> B(1,y=2) B(x=1, y=2) >>>
ちなみにattrsでは以下のように書く.attrsでは3.9以前のバージョンでも使える.
from attrs import define, field @define(kw_only=True) class A: a: int b: int @define class A: a: int b: int = field(kw_only=True)
slots オプション
全俺が欲しかったもの。
以前は明示的に __slots__
をつけないといけなかった。3.10からはこんな感じで書ける
from dataclasses import dataclass ## 3.9 以前のスタイル @dataclass class SlotedMessage: __slots__ = ["sender", "recipient", "body"] sender: str recipient: str body: str ## 3.10からはslotsを指定する @dataclass(slots=True) class SlotedMessage: sender: str recipient: str body: str
以前試した メモリの使用量見てみよう。
ちなみに実行前に pymperをinstallしてほしい。
pip install pympler
from typing import NamedTuple from pympler import asizeof from attrs import define from dataclasses import dataclass Message = NamedTuple("Message", [("sender", str), ("recipient", str), ("body", str)]) @dataclass class DataClassMessage: sender: str recipient: str body: str @dataclass(slots=True) class SlotedMessage: sender: str recipient: str body: str @define(auto_attribs=True, slots=True, weakref_slot=False) class AttrsMessage: sender: str recipient: str body: str if __name__ == "__main__": d = { "sender": "sender@exmaple.com", "recipient": "recipient.example.com", "body": "Hello, World!", } message = Message(**d) simple_data = DataClassMessage(**d) slotted = SlotedMessage(**d) attrs = AttrsMessage(**d) print( "NamedTuple %d, Dataclass %d, Slotted dataclass %d, attrs %d" % asizeof.asizesof(message, simple_data, slotted, attrs) )
% python aaa.py NamedTuple 272, Dataclass 528, Slotted dataclass 56, attrs 56
ここまでくると attrsのweakre_slots も入れて欲しかった気がする.
久しぶりにdataclassのドキュメントを読み返すことで発見がたくさんありました。 Python 開発者、ドキュメント書いてくれている皆様に感謝!
Python 3.11の新機能試す(1) - トレースバックのエラー位置の改善
app | version |
---|---|
Python | 3.11 rc1 |
本日試す機能
本日試すのはこちら。
PEP 657: Enhanced error locations in tracebacks 「トレースバックのエラー位置の改善」とでも訳すのがよさそう。
対応するPEP
試してみたコード
from dataclasses import dataclass @dataclass class Point: x: int y: int def manhattan_distance(p1, p2): return abs(p1.x - p2.x) + abs(p1.y - p2.y) if __name__ == "__main__": p1 = Point(x=1, y=2) p2 = None # Ouch!!! forget to initialize it for some reason print(manhattan_distance(p1, p2))
これを実行すると 3.10では
% python3.10 distance.py Traceback (most recent call last): File "/Users/masahito/src/python/try_3_11/distance.py", line 16, in <module> print(manhattan_distance(p1, p2)) File "/Users/masahito/src/python/try_3_11/distance.py", line 9, in manhattan_distance return abs(p1.x - p2.x) + abs(p1.y - p2.y) AttributeError: 'NoneType' object has no attribute 'x
どこでエラーになっているかはわからない。
けど、3.11で実行すると
% python3.11 distance.py Traceback (most recent call last): File "/Users/masahito/src/python/try_3_11/distance.py", line 16, in <module> print(manhattan_distance(p1, p2)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/masahito/src/python/try_3_11/distance.py", line 9, in manhattan_distance return abs(p1.x - p2.x) + abs(p1.y - p2.y) ^^^^ AttributeError: 'NoneType' object has no attribute 'x'
となって、エラーになっている行だけではなく、変数のどこで何が起こっている(今回の場合は変数がnone)のかが追いやすくなっていますね! これはなかなかいい
m1macbook air の環境をmacports -> homebrewに入れ替え
思うところがあってm1 macbook airを買ってからずっと使っていた macportsをやめてhomebrewに入れ替えてみた
対象 monteley 12.3
macportsをアンインストール
公式の以下の説明通りやればOKです。 guide.macports.org
注意点
ただし、rmコマンドで削除するときに以下のように permission denied
が出た場合はセキュリティ設定をチェックしてみた方が良いです。
フルディスクアクセスを以下のようにターミナル(またはあなたがお使いのterminal application)にフルディスクアクセスを与えてください。
homebrewをインストール
前は apple sillicon用のインストール方法はintel版と違っていた気がしたのですが、 今は一緒のようです。
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" % brew --version Homebrew 3.4.5 Homebrew/homebrew-core (git revision 76904b3d872; last commit 2022-04-09)
Cloud Loggingでミュート(disable)しているアラートの一覧を表示する
こちらのブログを読んでいてCloud Loggingでミュート(disable)しているアラートの一覧を表示したくなった。
やり方
gcloud commandを使うといけるっぽい.
例
アラートの名前を一覧表示する(jqを使用)
$ gcloud alpha monitoring policies list --project=PROJECT --filter=enabled:false --format=json \ | jq '.[].displayName'
注意点
理想
Datadogみたいに一時ミュートできると本当はいいんだけどなぁ
Gradle で「詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください」と表示されたときの対処(for build.gradle.kts)
レアキャラです。今回は久々なので小ネタです。
software | version |
---|---|
Java | 11.0.9.1 |
Gradle | 7.3.3 |
Gradle で「詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください」と表示される時があります。 build.gradleの時は以下の記事を参照。
ただ、この書き方だとbuild.gradle.kts(kotlinで書く方のやつ)だと動きません。 ではどう書くかというと以下のような感じになります
tasks {
withType<JavaCompile> {
options.compilerArgs.add("-Xlint:unchecked")
}
}
先人に感謝
参考
https://discuss.gradle.org/t/what-is-xlint-deprecation-and-how-to-use-it/40270
Python 3.10触ってみた(1) ~asyncio#get_event_loop
こんにちは, ミュージシャンの卵です.
Python3.10のリリース予定日の2021-10-04が近づいていますね。 そろそろどの辺が変わるのかも含めて調査を始めています。 asyncioのコードを書いてみて軽い変更があったことを見つけました。
asyncio
Python3.10でasyncioのコードを書いてみたらこんなwarningが出るようになりました。
import asyncio async def main(): print('Hello ...') await asyncio.sleep(1) print('... World!') loop = asyncio.get_event_loop() # ここでwarning loop.run_until_complete(main())
DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop()
調べた感じだとこういうことらしい
asyncio.get_event_loop() now emits a deprecation warning if there is no running event loop. In the future it will be an alias of get_running_loop(). asyncio functions which implicitly create a Future or Task objects now emit a deprecation warning if there is no running event loop and no explicit loop argument is passed: ensure_future(), wrap_future(), gather(), shield(), as_completed() and constructors of Future, Task, StreamReader, StreamReaderProtocol. (Contributed by Serhiy Storchaka in bpo-39529.)
ざっくり訳すと
asyncio.get_event_loop()は、実行中のイベントループがない場合、 deprecationの警告を出すようになりました。asyncio.get_event_loop() は、将来的には get_running_loop() のエイリアスになります。
というわけで asyncio.get_event_loop()
を呼ぶとこの警告が出るっぽい。
対策
どうやら asyncio.run
だとこのwarningが出ないことがわかってきた。
というわけで サクッとサンプルを書きたい時は asyncio.run()
を使い、
そうじゃない時はこんな感じでnew_event_loop -> set_event_loopするのが良いっぽい。
import asyncio # ものすごく略したコード loop = asyncio.new_event_loop() try: asyncio.set_event_loop(loop) loop.run_until_complete(main()) finally: asyncio.set_event_loop(None) loop.close()