例外
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