例外

1 >>> try:
2 ...     1 / 0
3 ... except ZeroDivisionError:
4 ...     print('error!')
5 ...     
6 error!

独自の例外クラスを定義するにはExceptionクラスから派生させる。

例外を投げるにはraise Exception()とする。

また、最後にキャッチされた例外を取得するにはsys.exception()とする。

 1 >>> import sys
 2 >>> class FooError(Exception):
 3 ...     pass
 4 ...     
 5 >>> try:
 6 ...     raise FooError()
 7 ... except Exception:
 8 ...     e = sys.exception()
 9 ...     print(type(e))
10 ...     
11 <class '__main__.FooError'>

例外オブジェクトを取得するにはasで変数を指定できる。こちらを使うべきだろう。

また、Exceptionクラスはコンストラクタで任意のタプルを受け取り、e.argsのように取得できるので、データを受け渡す必要があるならこれを使うとよい。

1 >>> try:
2 ...     raise Exception('foo', 'bar')
3 ... except Exception as e:
4 ...     print(type(e))
5 ...     print(e.args)
6 ...     
7 <class 'Exception'>
8 ('foo', 'bar')

クリーンアップ処理が必要ならfinally句を使う。

1 >>> try:
2 ...     pass
3 ... finally:
4 ...     print('done')

with

 1 >>> class Foo:
 2 ...     def __enter__(self):
 3 ...         return 'hi'
 4 ...     def __exit__(self, exc_type, exc_val, exc_tb):
 5 ...         print(exc_type, exc_val, exc_tb)
 6 ...         return True
 7 ...         
 8 >>> with Foo() as x:
 9 ...     print(x)
10 ...     raise Exception('foo')
11 ...     
12 hi
13 <class 'Exception'> foo <traceback object at 0x105745080>

ファイル

エンコーディング

Pythonはテキストモードでシステムのエンコーディングを用いる。これは特定の環境で問題を引き起こすので、utf8に固定してしまう方が望ましい。これはpythonの起動オプションか環境変数で設定できる。

Utf8モードが有効かどうかは以下のようにして確認できる。

1 >>> import sys
2 >>> sys.flags.utf8_mode
3 0

起動オプションで設定。

1 python3 -X utf8

環境変数で設定。

1 env PYTHONUTF8=1 python3

実際の実行可能スクリプトは以下のようになるだろう。

1 cat ./utf8.py 
2 #!/usr/bin/env PYTHONUTF8=1 python3
3 
4 import sys
5 print(sys.flags.utf8_mode)
* * *

io.TextIOBase

1 >>> with open('foo.txt', 'wt') as f:
2 ...     f.write('hello')
1 >>> with open('foo.txt', 'rt') as f:
2 ...     s = f.read()
3 ...     print(s)
4 ...     
5 hello

io.RawIOBase

 1 >>> with open('foo.bin', 'wb') as f:
 2 ...     b = (99).to_bytes()
 3 ...     f.write(b)
 4 ...     
 5 1
 6 >>> with open('foo.bin', 'rb') as f:
 7 ...     b = f.read()
 8 ...     i = int.from_bytes(b)
 9 ...     print(i)
10 ...     
11 99

実際にバイト列を読み書きするにはもう少し調べてみる必要があるだろう。

pip

Pythonパッケージマネージャ。

インストール済みのパッケージを表示する
python -m pip list
パッケージを検索する
WebブラウザでPyPIにアクセスして行う
パッケージをインストールする
python -m pip install requests
パッケージの情報を表示する
python -m pip show requests
パッケージをアップデートする
python -m pip install --upgrade requests

importlib

Pythonインタプリタの中でモジュールをリロードする時に使う。

いつも使うので~/.zshrcの中でPYTHONSTARTUPに設定して常時読み込まれるようにしておく。

1 import aecpic
2 from importlib import reload
3 reload(aecpic)

pdb

Pythonデバッガー。

モジュールのインポートなどは必要ない。組み込み関数breakpoint()をコードに挿入するだけで自動的にデバッガーが立ち上がる。

h, help
デバッガーコマンドを表示する
d, down
下のフレームに移動
u, up
上のスタックフレームに移動
a, args
関数の引数を表示する
s, step
ステップ実行
l
ソースコードを表示
c, continue
実行を継続
p
式の値を表示する
pp
pと同様だが 表示にpprintを使う
q, quit
デバッガを終了する

main

1 if __name__ == '__main__':
2     print('hi')

doctest

1 cat t.py
2 def add2(x):
3     '''
4     >>> import t
5     >>> t.add2(3)
6     5
7     '''
8     return x + 2
9 python3 -m doctest t.py

pydoc

1 python3 -m pydoc t

HTML形式でドキュメントを書き出す。

1 python3 -m pydoc -w t

ローカルHTTPサーバーを起動しドキュメントを開く。

1 python3 -m pydoc -b

os

環境変数を取得する

1 >>> import os
2 >>> os.environ['HOME']

subprocess

1 import subprocess
2 r = subprocess.run(['ls', '-l'], capture_output = True)
3 r.stdout
4 
5 r = subprocess.run(['curl', 'https://moli-green.xyz'], capture_output = True)
6 r.stdout

tempfile

1 import tempfile
2 f = tempfile.NamedTemporaryFile(delete=False, suffix='.png')
3 f.name
4 # '/tmp/tmpb30bxpet.png'
5 f.close()

json

1 >>> x = {'foo': 3, 'bar': [4, 5, 6]}
2 >>> j = json.dumps(x)
3 >>> j
4 '{"foo": 3, "bar": [4, 5, 6]}'
5 >>> o = json.loads(j)
6 >>> o
7 {'foo': 3, 'bar': [4, 5, 6]}

多分、特定のインターフェースをサポートしていないオブジェクトはシリアライズできないようだけど、よくわからない。

パターンマッチと併用するのが良いだろう。

1 >>> match o:
2 ...     case {'foo': x, 'bar': y}:
3 ...         print(x)
4 ...         for i in y:
5 ...             print(i)
6 ...

組み込みクラスとマッチさせた方がセキュリティ的には良いようだが。まあ、型が合わないと後々実行時エラーが発生してわかりそうではある。

1 >>> match o:
2 ...     case {'foo': str() as x, 'bar': list(y)}:
3 ...         print(x)
4 ...         for i in y:
5 ...             print(i)
6 ... 

Requests

1 import requests

GET

1 r = requests.get('https://moli-green.xyz')

ヘッダを追加するならこう。

1 h = {'foo': 'bar', 'baz': 'hoge'}
2 r = requests.get('https://moli-green.xyz', headers=h)

POST, PUT

* * *

mimetypeを取得するにはこう。

1 >>> r = requests.get('https://moli-green.xyz/img.webp')
2 >>> r.headers['content-type']
3 'image/webp'

mimetypes

拡張子からファイルタイプを判別する。

 1 >>> import mimetypes
 2 >>> mimetypes.guess_type('https://moli-green.xyz/img.png')
 3 ('image/png', None)
 4 >>> mimetypes.guess_type('https://moli-green.xyz/img.jpg')
 5 ('image/jpeg', None)
 6 >>> mimetypes.guess_type('https://moli-green.xyz/img.jpeg')
 7 ('image/jpeg', None)
 8 >>> mimetypes.guess_type('https://moli-green.xyz/img.webp')
 9 ('image/webp', None)
10 >>> mimetypes.guess_type('https://moli-green.xyz/img.avif')
11 ('image/avif', None)
12 >>> mimetypes.guess_type('https://moli-green.xyz/img.j2k')
13 (None, None)
14 >>> mimetypes.guess_type('https://moli-green.xyz/img.jp2')
15 ('image/jp2', None)
16 >>> mimetypes.guess_type('https://moli-green.xyz/img.qoi')
17 (None, None)

pillow

画像処理ライブラリ。(PILのフォーク)

画像の読み込みと保存。

1 >>> from PIL import Image
2 >>> img = Image.open('img.png')
3 >>> img.save('img.webp')

pillowには他の画像形式に対応するためのプラグインが公開されていることもあるようなので、PyPIで探してみるといいだろう。

パターンマッチ

キャプチャーパターンには*によるアンパックが使える。これはパターンマッチの機能というわけではなく、式リストの機能だと思われる。

1 >>> match input().split():
2 ...     case ["foo", *objs]:
3 ...         for i in objs:
4 ...             print(i)

_は何にでも一致する。

|は or。

1 >>> match input():
2 ...     case 'foo' | 'bar':
3 ...         print('ok')
4 ...     case _:
5 ...         print('other')

マッチしたものを変数に取得したければasを使う。

1 >>> match input().split():
2 ...     case ["foo", ("bar" | "baz") as x]:
3 ...         print(x)

辞書型へのパターンマッチの例

1 >>> d = dict(x=2, y=3, z=[10, 20, 30])
2 >>> match d:
3 ...     case {'x': 2 as x, 'z': z, **o}:
4 ...         print(x, z, o)

dataclasses

argpase

大変複雑だが、最低限次のことを覚えておけばいいだろう。

1 >>> import argparse
2 >>> p = argparse.ArgumentParser()
3 >>> p.add_argument('-f', '--foo', help='Foo!', action='store_true')
4 >>> p.add_argument('url')
5 >>> arg = p.parse_args('https://example.com'.split())
6 >>> print(arg.foo)
7 False
8 >>> print(arg.url)
9 https://example.com