13章学習記録 » 履歴 » バージョン 2
Tatsuya ISHIGAKI, 2025/07/31 14:29
| 1 | 1 | Tatsuya ISHIGAKI | # 第13章 特定のデータフォーマットを扱う |
|---|---|---|---|
| 2 | |||
| 3 | ## CSV ファイルを扱う csv |
||
| 4 | CSV, TSV フォーマットのファイルの読み取り、書き込みを行う機能 |
||
| 5 | |||
| 6 | - CSV ファイルの読み込みと書き込み |
||
| 7 | |||
| 8 | |関数名|解説|戻り値| |
||
| 9 | |---|---|---| |
||
| 10 | |`reader(csvfile, dialect='excel', **fmtparams)`|CSV ファイルの各行を反復処理するような `reader` オブジェクトを返す|`reader` オブジェクト| |
||
| 11 | |`writer(csvfile, dialect='excel', **fmtparams)`|CSV ファイルのデータを指定方法で書き込むための `writer` オブジェクトを返す|`writer` オブジェクト| |
||
| 12 | |||
| 13 | - `csvfile` には、イテレータープロトコルをサポートするオブジェクトを指定 |
||
| 14 | - `dialect` には、以下の **書式化パラメーターセット** 、または `Dialect` サブクラスのインスタンスを指定できる |
||
| 15 | - `excel` Excel で出力される CSV ファイル |
||
| 16 | - `excel-tab` Excel で出力される TSV ファイル |
||
| 17 | - `unix` 終端記号を `\n` とするファイル |
||
| 18 | |||
| 19 | <br>書式化パラメーターセットによる、各書式化パラメーターのデフォルト値 |
||
| 20 | |パラメーター<br>セット|delimiter|quatechar|skipinitialspace|lineterminator| |
||
| 21 | |---|---|---|---|---| |
||
| 22 | |`excel`|`,`|`"`|False|`\r\n`| |
||
| 23 | |`excel-tab`|`\t`|`"`|False|`\r\n`| |
||
| 24 | |`unix`|`,`|`"`|False|`\n`| |
||
| 25 | |||
| 26 | <br>`Dialect` クラスの主な属性 |
||
| 27 | |属性|デフォルト|解説| |
||
| 28 | |---|---|---| |
||
| 29 | |`delimiter`|`,`|区切り文字 (1文字からなる文字列)| |
||
| 30 | |`quotechar`|`"`|引用符文字| |
||
| 31 | |`skipinitialspace`|False|Trueの場合、`delimiter` の直後に続く空白は無視される| |
||
| 32 | |`lineterminator`|`\r\n`|`writer` が使用する、各行の終わりを表す文字列| |
||
| 33 | |||
| 34 | - `reader` オブジェクトで CSV 読み込み |
||
| 35 | |||
| 36 | ``` |
||
| 37 | "id","都道府県","人口(人)","面積(km2)" |
||
| 38 | "1","東京都","13900000","2194.05" |
||
| 39 | "2","神奈川県","9200000","2416.10" |
||
| 40 | "3","千葉県","6200000","5157.50" |
||
| 41 | "4","埼玉県","7300000","3797.75" |
||
| 42 | ``` |
||
| 43 | |||
| 44 | ```python |
||
| 45 | >>> import csv |
||
| 46 | >>> with open("01_sample.csv", mode="r", encoding="utf-8") as f: |
||
| 47 | ... reader = csv.reader(f) |
||
| 48 | ... for row in reader: |
||
| 49 | ... print(row) |
||
| 50 | ... |
||
| 51 | ['id', '都道府県', '人口(人)', '面積(km2)'] |
||
| 52 | ['1', '東京都', '13900000', '2194.05'] |
||
| 53 | ['2', '神奈川県', '9200000', '2416.10'] |
||
| 54 | ['3', '千葉県', '6200000', '5157.50'] |
||
| 55 | ['4', '埼玉県', '7300000', '3797.75'] |
||
| 56 | ``` |
||
| 57 | |||
| 58 | ```python |
||
| 59 | >>> dialect = reader.dialect |
||
| 60 | >>> dialect.quotechar |
||
| 61 | '"' |
||
| 62 | >>> dialect.lineterminator |
||
| 63 | '\r\n' |
||
| 64 | >>> dialect.doublequote |
||
| 65 | True |
||
| 66 | >>> dialect.skipinitialspace |
||
| 67 | False |
||
| 68 | >>> dialect.delimiter |
||
| 69 | ',' |
||
| 70 | ``` |
||
| 71 | |||
| 72 | - `writer` オブジェクトで CSV 書き込み |
||
| 73 | |||
| 74 | |メソッド名|解説| |
||
| 75 | |---|---| |
||
| 76 | |`writerow(row)`|データを書式化し、`writer` のファイルオブジェクトへ書き込む<br>`row` には文字列か数値のイテラブルを指定| |
||
| 77 | |`writerows(rows)`|複数行を書き込む<br>`rows` には `writerow()` の `row` と同様のオブジェクトのイテラブルを指定| |
||
| 78 | |||
| 79 | ```python |
||
| 80 | >>> with open("writetest.tsv", mode="w", encoding="utf-8") as f: |
||
| 81 | ... writer = csv.writer(f, dialect="excel-tab") |
||
| 82 | ... for i in range(5): |
||
| 83 | ... writer.writerow([i, "x", i, "=", i**2]) |
||
| 84 | ... |
||
| 85 | 11 |
||
| 86 | 11 |
||
| 87 | 11 |
||
| 88 | 11 |
||
| 89 | 12 |
||
| 90 | ``` |
||
| 91 | |||
| 92 | ``` |
||
| 93 | 0 x 0 = 0 |
||
| 94 | 1 x 1 = 1 |
||
| 95 | 2 x 2 = 4 |
||
| 96 | 3 x 3 = 9 |
||
| 97 | 4 x 4 = 16 |
||
| 98 | ``` |
||
| 99 | |||
| 100 | - 辞書データを用いた CSV ファイルの読み込みと書き込み |
||
| 101 | - class `DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwargs)` |
||
| 102 | - `f` イテレータープロトコルをサポートするオブジェクト |
||
| 103 | - `fieldnames` 辞書のキーをシーケンスで指定 (未指定の場合は `f` の最初の行の値が使用される) |
||
| 104 | - `restkey` `restval` 実際に読み込んだデータが、フィールド数 (`fieldnames` または `f` の1行目) と不一致である場合に使用される値 |
||
| 105 | - 実データのフィールド数が多い場合、残りの列の値はリストとしてまとめられて `restkey` キーの値となる |
||
| 106 | - 実データのフィールド数が少ない場合、足りない値は `restval` によって埋められる |
||
| 107 | - `dialect` (略) |
||
| 108 | - **戻り値** `DictReader` オブジェクト |
||
| 109 | - class `DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwargs)` |
||
| 110 | - `f` (略) |
||
| 111 | - `fieldnames` 書き込み時に渡される辞書の値をどの順でファイルへ書き出すかをシーケンスで指定 |
||
| 112 | - `restval` fieldnames に指定のキーが書き込みデータに存在しない場合に値として使用する文字列を指定 |
||
| 113 | - `extrasaction` fieldnames に存在しないキーが書き込みデータに存在する場合の動作 |
||
| 114 | - `raise` ValueError 送出 |
||
| 115 | - `ignore` 無視される |
||
| 116 | - `dialect` (略) |
||
| 117 | - **戻り値** `DictWriter` オブジェクト |
||
| 118 | |||
| 119 | ```python |
||
| 120 | >>> import csv |
||
| 121 | >>> with open('01_sample.csv', mode='r', encoding='utf-8') as f: |
||
| 122 | ... for row in csv.DictReader(f): |
||
| 123 | ... print(row) |
||
| 124 | ... |
||
| 125 | {'id': '1', '都道府県': '東京都', '人口(人)': '13900000', '面積(km2)': '2194.05'} |
||
| 126 | {'id': '2', '都道府県': '神奈川県', '人口(人)': '9200000', '面積(km2)': '2416.10'} |
||
| 127 | {'id': '3', '都道府県': '千葉県', '人口(人)': '6200000', '面積(km2)': '5157.50'} |
||
| 128 | {'id': '4', '都道府県': '埼玉県', '人口(人)': '7300000', '面積(km2)': '3797.75'} |
||
| 129 | ``` |
||
| 130 | |||
| 131 | - `DictWriter` には、ヘッダーを書き込むメソッド `writeheader(row)` がある |
||
| 132 | ```python |
||
| 133 | import csv |
||
| 134 | |||
| 135 | data = [ |
||
| 136 | {'都道府県': '東京都', '人口密度(人/km2)': 6335}, |
||
| 137 | {'都道府県': '神奈川県', '人口密度(人/km2)': 3807}, |
||
| 138 | {'都道府県': '千葉県', '人口密度(人/km2)': 1202}, |
||
| 139 | ] |
||
| 140 | |||
| 141 | with open('result.csv', newline='', mode='w', encoding='utf-8') as write_file: |
||
| 142 | fieldnames = ['都道府県', '人口密度(人/km2)'] # ヘッダーの要素順を指定する |
||
| 143 | writer = csv.DictWriter(write_file, fieldnames=fieldnames) |
||
| 144 | writer.writeheader() # DictWriterのメソッドwriteheaderを使用してヘッダー行を書き込み |
||
| 145 | writer.writerows(data) # データの一括書き込み |
||
| 146 | ``` |
||
| 147 | |||
| 148 | - Dialect を推測して生成する Sniffer クラス |
||
| 149 | |||
| 150 | |クラスメソッド名|解説|戻り値| |
||
| 151 | |---|---|---| |
||
| 152 | |`sniff(sample, delimiters=None)`|`sample` のデータを解析し、推測結果を返す|`Dialect` サブクラス| |
||
| 153 | |`has_header(sample)`|ヘッダーの有無を判定する|bool| |
||
| 154 | |||
| 155 | ## 13.2 JSON を扱う json |
||
| 156 | JSON フォーマットを扱うための機能 |
||
| 157 | |||
| 158 | - JSON のエンコードとデコード |
||
| 159 | - 関数 `dump(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)` |
||
| 160 | - `obj` エンコード対象オブジェクト |
||
| 161 | - `skipkeys` True の場合、辞書キーに `str` `int` `float` `bool` `None` 以外を指定しても TypeError を送出しない |
||
| 162 | - `ensure_ascii` True の場合、非 ascii 文字列はエスケープされる (日本語などをそのまま出力したい場合は False にする) |
||
| 163 | - `check_circular` True の場合、リストや辞書での循環参照がチェックされ無限再帰を防ぐ (False で循環参照が見つかると RecursionError) |
||
| 164 | - `allow_nan` False の場合、許容範囲外 float (nan, inf, -inf) を検出すると ValueError |
||
| 165 | - `cls` カスタマイズした `JSONEncoder` サブクラスを使用する場合に指定 |
||
| 166 | - `indent` インデントのスペース数を整数指定 |
||
| 167 | - `separators` セパレーター文字を `(item_separator, key_separator)` のタプルで指定 |
||
| 168 | - `default` シリアライズできないオブジェクトに対して呼び出す関数を指定 |
||
| 169 | - `sort_keys` True の場合、キーでソートされる |
||
| 170 | - **戻り値** JSON 形式の str |
||
| 171 | |||
| 172 | ```python |
||
| 173 | >>> import json |
||
| 174 | >>> dbinfo = [{"db1": {"id": "user1", "pw": "pass1", "failover": True, "host": [{"ip": "192.168.0.1", "port": 8021},{"i\p": "192.168.0.2", "port": 8021}]}}, {"db2": {"id": "user2", "pw": "pass2", "failover": False, "host": [{"ip": "192.168\.0.3", "port": 8021}]}}] |
||
| 175 | >>> print(json.dumps(dbinfo, indent=4)) |
||
| 176 | [ |
||
| 177 | { |
||
| 178 | "db1": { |
||
| 179 | "id": "user1", |
||
| 180 | "pw": "pass1", |
||
| 181 | "failover": true, |
||
| 182 | "host": [ |
||
| 183 | { |
||
| 184 | "ip": "192.168.0.1", |
||
| 185 | "port": 8021 |
||
| 186 | }, |
||
| 187 | { |
||
| 188 | "ip": "192.168.0.2", |
||
| 189 | "port": 8021 |
||
| 190 | } |
||
| 191 | ] |
||
| 192 | } |
||
| 193 | }, |
||
| 194 | { |
||
| 195 | "db2": { |
||
| 196 | "id": "user2", |
||
| 197 | "pw": "pass2", |
||
| 198 | "failover": false, |
||
| 199 | "host": [ |
||
| 200 | { |
||
| 201 | "ip": "192.168.0.3", |
||
| 202 | "port": 8021 |
||
| 203 | } |
||
| 204 | ] |
||
| 205 | } |
||
| 206 | } |
||
| 207 | ] |
||
| 208 | ``` |
||
| 209 | |||
| 210 | - 関数 `loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)` |
||
| 211 | - `s` デコード対象のオブジェクト (str, bytes, bytearray) |
||
| 212 | - `cls` カスタマイズした `JSONDecoder` サブクラスを使用する場合に指定 |
||
| 213 | - `object_hook` オブジェクトリテラルがデコードされた結果に対して呼ばれる関数を指定 (デコード結果が関数戻り値に置換される) |
||
| 214 | - `parse_float` JSON に含まれる浮動小数点数 (文字列) を扱う関数を指定 (None なら `float()` が使用される) |
||
| 215 | - `parse_int` JSON に含まれる整数 (文字列) を扱う関数を指定 (None なら `int()` が使用される) |
||
| 216 | - `parse_constant` JSON に含まれる `'-Infinity'` `'Infinity'` `'NaN'` を扱う関数を指定 |
||
| 217 | - `object_pairs_hook` ペアの順序付きリストのデコード結果に対して呼ばれる関数を指定 (`object_hook` より優先される) |
||
| 218 | - **戻り値** Python オブジェクト |
||
| 219 | |||
| 220 | ```python |
||
| 221 | >>> jsonstr = '[{"name": "smith", "age": 41, "height": 167.5}, {"name": "sabakan", "age": 3}]' |
||
| 222 | >>> pyobj = json.loads(jsonstr) |
||
| 223 | >>> pyobj |
||
| 224 | [{'name': 'smith', 'age': 41, 'height': 167.5}, {'name': 'sabakan', 'age': 3}] |
||
| 225 | >>> type(pyobj) |
||
| 226 | <class 'list'> |
||
| 227 | >>> type(pyobj[0]) |
||
| 228 | <class 'dict'> |
||
| 229 | >>> pyobj[0] |
||
| 230 | {'name': 'smith', 'age': 41, 'height': 167.5} |
||
| 231 | ``` |
||
| 232 | |||
| 233 | <br>エンコード変換表 |
||
| 234 | |Python|→|JSON| |
||
| 235 | |---|---|---| |
||
| 236 | |辞書||オブジェクト| |
||
| 237 | |リスト、タプル||配列| |
||
| 238 | |文字列||文字列| |
||
| 239 | |整数、浮動小数点数、<br>intやfloatの派生列挙型||数値| |
||
| 240 | |True||true| |
||
| 241 | |False||| |
||
| 242 | |||| |
||
| 243 | |||
| 244 | <br>デコード変換表 |
||
| 245 | |JSON|→|Python| |
||
| 246 | |---|---|---| |
||
| 247 | |オブジェクト||辞書| |
||
| 248 | |配列||リスト| |
||
| 249 | |文字列||文字列| |
||
| 250 | |数値||整数、浮動小数点数| |
||
| 251 | |true||True| |
||
| 252 | |false||False| |
||
| 253 | |null||None| |
||
| 254 | |||
| 255 | - JSON のエンコードとデコード (ファイルオブジェクト) |
||
| 256 | - 関数 `dump(obj, fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)` |
||
| 257 | - `fp` 書き込み先ファイルオブジェクト |
||
| 258 | - **戻り値** None |
||
| 259 | - 関数 `load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)` |
||
| 260 | - `fp` 読み込み元ファイルオブジェクト |
||
| 261 | - **戻り値** Python オブジェクト |
||
| 262 | |||
| 263 | - JSON のコマンドラインインターフェースを提供している json.tool |
||
| 264 | - JSON 文字列 (`curl で受け取ったレスポンスなど) を渡すだけで整形できる |
||
| 265 | - `python -m json.tool -h` でヘルプ |
||
| 266 | |||
| 267 | ## 13.3 INI ファイルを扱う configparser |
||
| 268 | Windows OS で設定ファイルとして多く使用される INI ファイル (他の場所でも多く使用されている) 、および INI ファイルに似た構造の設定ファイルを扱う |
||
| 269 | |||
| 270 | - サポートされる INI ファイルの構造 ([webドキュメントより](https://docs.python.org/ja/3.13/library/configparser.html#supported-ini-file-structure)) |
||
| 271 | - 各セクションは `[セクション名]` で始まる領域 |
||
| 272 | - デフォルトではセクション名は改行を含まない任意の文字列 |
||
| 273 | - セクション名は大文字小文字が区別される |
||
| 274 | - セクション内には、指定文字列 (デフォルトでは、 `=` および `:`) を使った キー/値 要素が並ぶ |
||
| 275 | - キー、値はすべて文字列として扱われるが、取得時に変換もするメソッドが用意されている |
||
| 276 | - `getboolean()` `getint()` `getfloat()` |
||
| 277 | - キーは大文字小文字が区別されず、すべて小文字として扱われる (書き込み時も小文字) |
||
| 278 | - キー、値の前後の空白は基本的に除去される |
||
| 279 | - 値は複数行に渡って記述でき、その場合は2行目以降を1行目よりインデントさせる |
||
| 280 | - コメントは行頭に特定文字 (デフォルトでは、`#` および `;`) を付けた行全体 (インデントも可能) |
||
| 281 | - 最初のセクション名は省略可能で、その場合は読み込み時にオプション `allow_unnamed_section=True` とすることで、無名セクションを扱える |
||
| 282 | - 無名セクションへは、セクション名の代わりに `configparser.UNNAMED_SECTION` を使用してアクセスする |
||
| 283 | |||
| 284 | - INI ファイルを読み込む |
||
| 285 | |||
| 286 | ConfigParser インスタンスのメソッド |
||
| 287 | |メソッド|解説|戻り値| |
||
| 288 | |---|---|---| |
||
| 289 | |`read_string(string)`|指定文字列を INI フォーマットとして解析する|None| |
||
| 290 | |`read(filenames, encoding=None)`|指定した INI ファイルを読み込む<br>`filenames` にはリストで複数渡せる|list (解析できたファイル名)| |
||
| 291 | |`sections()`|読み込んだ INI 内のセクション名一覧を返す|list (セクション名)| |
||
| 292 | |`options(section)`|指定セクションのキー一覧を返す|list (キー)| |
||
| 293 | |||
| 294 | - DEFAULT セクション |
||
| 295 | - 特定セクションの存在しないキーを参照した場合、DEFAULT セクションのキーを参照して値が返される |
||
| 296 | |||
| 297 | - INI ファイルの高度な利用 (値の補完) |
||
| 298 | - INI ファイル内の他の場所に記載した内容を再利用 (値の補完 = interpolation) する |
||
| 299 | - 値の補完方法クラスをコンストラクタに指定することで行う (クラスは configparser モジュール内) |
||
| 300 | - `ConfigParser(interpolation=BasicInterpolation)` (指定しない場合と同じ) |
||
| 301 | - `ConfigParser(interpolation=ExtendedInterpolation)` |
||
| 302 | |||
| 303 | <br>**BasicInterpolation** (セクション内の値補完. `%(キー)s` で参照する) |
||
| 304 | ``` |
||
| 305 | [USER_A] |
||
| 306 | home_dir = /home/user_a |
||
| 307 | mail_dir = %(home_dir)s/mail |
||
| 308 | group = Developer |
||
| 309 | ``` |
||
| 310 | |||
| 311 | ```python |
||
| 312 | >>> config = ConfigParser() |
||
| 313 | >>> config.read('config_interp.ini') |
||
| 314 | ['config_interp.ini'] |
||
| 315 | >>> config['USER_A']['mail_dir'] |
||
| 316 | '/home/user_a/mail' |
||
| 317 | ``` |
||
| 318 | |||
| 319 | <br>**ExtendedInterpolation** (セクション外も補完可能: `${キー}` `${セクション名:キー}` で参照する) |
||
| 320 | ``` |
||
| 321 | [USER_A] |
||
| 322 | home_dir = /home/user_a |
||
| 323 | mail_dir = ${home_dir}/mail |
||
| 324 | group = Developer |
||
| 325 | |||
| 326 | [USER_B] |
||
| 327 | group = ${USER_A:group} |
||
| 328 | ``` |
||
| 329 | |||
| 330 | ```python |
||
| 331 | >>> from configparser import ConfigParser, ExtendedInterpolation |
||
| 332 | >>> config = ConfigParser(interpolation=ExtendedInterpolation()) |
||
| 333 | >>> config.read('config_exinterp.ini') |
||
| 334 | ['config_exinterp.ini'] |
||
| 335 | >>> config['USER_B']['group'] |
||
| 336 | 'Developer' |
||
| 337 | ``` |
||
| 338 | |||
| 339 | ## 13.4 YAML を扱う PyYAML |
||
| 340 | |||
| 341 | - YAML ファイルの読み込み |
||
| 342 | |||
| 343 | |関数名|解説|戻り値| |
||
| 344 | |---|---|---| |
||
| 345 | |`load(stream, Loader)`|YAML で記述されたファイルを読み込む|Python オブジェクト| |
||
| 346 | |`load_all(stream, Loader)`|「---」で区切られた YAML で記述されたファイルを読み込む|Python オブジェクト (generator)| |
||
| 347 | |`safe_load(stream)`|`load()` に `Loader=yaml.SafeLoader` を指定したもの|Python オブジェクト| |
||
| 348 | |`safe_load_all()`|`load_all()` に `Loader=yaml.SafeLoader` を指定したもの|Python オブジェクト (generator)| |
||
| 349 | |||
| 350 | - 関数の引数 `Loader` に指定できるもの |
||
| 351 | |||
| 352 | |Loader|解説| |
||
| 353 | |---|---| |
||
| 354 | |`BaseLoader`|基本的な YAML のみをロードする<br>すべてのスカラーは文字列としてロードされる| |
||
| 355 | |`SafeLoader`|YAML のサブセットを安全にロードする| |
||
| 356 | |`FullLoader`|基本的に YAML の全機能を受け入れるが、任意コード実行は一部制限 (デフォルト Loader)| |
||
| 357 | |`UnsafeLoader`|YAML の全機能を使用可能で、任意コード実行もできる| |
||
| 358 | |||
| 359 | - YAML でキー `!!python/object:` を指定して記載すると、任意の Python オブジェクトが生成可能 |
||
| 360 | - 生成オブジェクトから処理を実行可能 |
||
| 361 | - この機能への対応が、Loader によって制御されている |
||
| 362 | |||
| 363 | <br>**単独ドキュメント** |
||
| 364 | ``` |
||
| 365 | --- |
||
| 366 | database: |
||
| 367 | host: localhost |
||
| 368 | port: 3306 |
||
| 369 | db: test |
||
| 370 | user: test |
||
| 371 | smtp_host: localhost |
||
| 372 | ``` |
||
| 373 | |||
| 374 | ```python |
||
| 375 | >>> import yaml |
||
| 376 | >>> with open("sample1.yml", "r") as f: |
||
| 377 | ... y1 = yaml.safe_load(f) |
||
| 378 | ... y1 |
||
| 379 | ... |
||
| 380 | {'database': {'host': 'localhost', 'port': 3306, 'db': 'test', 'user': 'test'}, 'smtp_host': 'localhost'} |
||
| 381 | ``` |
||
| 382 | |||
| 383 | <br>**複数ドキュメント** |
||
| 384 | ``` |
||
| 385 | --- |
||
| 386 | order: 1 |
||
| 387 | menu: ham |
||
| 388 | --- |
||
| 389 | order: 2 |
||
| 390 | menu: egg |
||
| 391 | ``` |
||
| 392 | |||
| 393 | ```python |
||
| 394 | >>> with open("sample2.yml", "r") as f: |
||
| 395 | ... y2 = yaml.safe_load(f) # 複数ドキュメントに対して load() はエラー |
||
| 396 | ... y2 |
||
| 397 | ... |
||
| 398 | Traceback (most recent call last): |
||
| 399 | ...(略)... |
||
| 400 | yaml.composer.ComposerError: expected a single document in the stream |
||
| 401 | in "sample2.yml", line 2, column 1 |
||
| 402 | but found another document |
||
| 403 | in "sample2.yml", line 4, column 1 |
||
| 404 | ``` |
||
| 405 | |||
| 406 | ```python |
||
| 407 | >>> with open("sample2.yml", "r") as f: |
||
| 408 | ... y3 = yaml.safe_load_all(f) # 複数ドキュメントに対しては load_all() |
||
| 409 | ... for y in y3: # load_all() はジェネレーターを生成し、毎取得時にファイル参照するので、with 内で読み込みを完了させる |
||
| 410 | ... y |
||
| 411 | ... |
||
| 412 | {'order': 1, 'menu': 'ham'} |
||
| 413 | {'order': 2, 'menu': 'egg'} |
||
| 414 | ``` |
||
| 415 | |||
| 416 | - YAML ファイルの書き込み |
||
| 417 | |||
| 418 | |関数名|解説|戻り値| |
||
| 419 | |---|---|---| |
||
| 420 | |`dump(data, stream=None, Dumper=Dumper, **kwds)`|Python オブジェクトを YAML 文字列へ変換する|文字列または `stream` で指定した型| |
||
| 421 | |`safe_dump(data, stream=None, **kwds)`|`dump()` と同じだが、標準の YAML タグ以外の変換はエラー|文字列または `stream` で指定した型| |
||
| 422 | |||
| 423 | - `**kwds` 部分の代表的引数 |
||
| 424 | |||
| 425 | |引数|解説| |
||
| 426 | |---|---| |
||
| 427 | |`indent`|インデントのスペース数を数値指定| |
||
| 428 | |`explicit_start`|True の場合、先頭に「---」が含まれる (デフォルトは False)| |
||
| 429 | |`default_flow_style`|True の場合 (デフォルト)、YAML のフロースタイル<br>False の場合、ブロックスタイル<br>(※動作確認時は、デフォルトが False になっていた)| |
||
| 430 | |||
| 431 | |||
| 432 | ```python |
||
| 433 | >>> hosts = {'web_server': ['192.168.0.2', '192.168.0.3'], 'db_server': ['192.168.10.7']} |
||
| 434 | >>> with open('dump.yml', 'w') as f: |
||
| 435 | ... f.write(yaml.dump(hosts, default_flow_style=False)) |
||
| 436 | ... |
||
| 437 | 66 |
||
| 438 | ``` |
||
| 439 | |||
| 440 | ``` |
||
| 441 | db_server: |
||
| 442 | - 192.168.10.7 |
||
| 443 | web_server: |
||
| 444 | - 192.168.0.2 |
||
| 445 | - 192.168.0.3 |
||
| 446 | ``` |
||
| 447 | |||
| 448 | ## 13.5 Excel を扱う openpyxl |
||
| 449 | 2 | Tatsuya ISHIGAKI | MS Excel の読み書きを Python で行うための機能を提供する |
| 450 | `pip install openpyxl` |
||
| 451 | 1 | Tatsuya ISHIGAKI | |
| 452 | 2 | Tatsuya ISHIGAKI | - Excel の読み込み |
| 453 | - 関数 `load_workbook(filename, read_only=False, use_iterators=False, keep_vba=False, guess_types=False, data_only=False)` |
||
| 454 | - `filename` Excel ファイルパス |
||
| 455 | - `read_only` True の場合、読み取り専用となり編集できない |
||
| 456 | - `data_only` True の場合、セルの値が式の場合に評価結果を取得する |
||
| 457 | - **戻り値** `Workbook` オブジェクト |
||
| 458 | - 参照 |
||
| 459 | - `Workbook` の属性 `sheetnames` で、ワークシート名のリストが取得可能 |
||
| 460 | - `Workbook` からはワークシート名をキーとして辞書と同様に `Worksheet` が取得可能 |
||
| 461 | - `Worksheet` からはセル名をキーとして辞書と同様に `Cell` が取得可能 |
||
| 462 | - メソッド `cell(row=None, column=None, value=None)` でも取得可能 |
||
| 463 | - `Cell` の値は属性 `value` で取得可能 |
||
| 464 | - Excel の書き込み |
||
| 465 | - `Cell` に値を設定するには、辞書の値設定と同様に行う |
||
| 466 | 1 | Tatsuya ISHIGAKI | |
| 467 | 2 | Tatsuya ISHIGAKI | <br>Workbook のメソッド |
| 468 | |メソッド名|解説|戻り値| |
||
| 469 | |---|---|---| |
||
| 470 | |`create_sheet(title=None, index=None)`|シートを `index` 位置に挿入する (0 なら先頭)|`Worksheet` オブジェクト| |
||
| 471 | |`save(filename)`|ファイルパス `filename` へ Excel ファイルを保存する|None| |
||
| 472 | - スタイルの適用 |
||
| 473 | - フォント |
||
| 474 | - `openpyxl.styles.Font` オブジェクトを作成し、セルの `font` 属性に設定する |
||
| 475 | - セルの色、模様 (塗りつぶし) |
||
| 476 | - `openpyxl.styles.PatternFill` オブジェクトを作成し、セルの `fill` 属性に設定する |
||
| 477 | - 罫線 |
||
| 478 | - `openpyxl.styles.Border` オブジェクトを作成し、セルの `border` 属性に設定する |
||
| 479 | - `Border` に設定する各辺の属性は `openpyxl.styles.Side` オブジェクトを設定する |
||
| 480 | - 文字位置 |
||
| 481 | - `openpyxl.styles.Alignment` オブジェクトを作成し、セルの `alignment` 属性に設定する |
||
| 482 | - チャートの挿入 |
||
| 483 | - `openpyxl.chart` に様々なチャートあり (例 `LineChart` `BarChart`) |
||
| 484 | |||
| 485 | ### 注意点 |
||
| 486 | - 表示形式が「ユーザー定義」のセルは注意、日付がシリアル値取得されるなどあり (openpyxl.utils パッケージに変換ツールなどが存在する) |
||
| 487 | - Excel ファイルが他で開かれていると、保存時に PermissionError が発生する |
||
| 488 | - `data_only=True` で式の解決値を取得できるのは、Excel ソフトで一度以上開いた場合のみ |
||
| 489 | - プログラムで書き込んで、Excel で開かないまま読み込むと解決値は取得できない |
||
| 490 | - これは Excel で開いた際に式解決が行われて結果がキャッシュされる為 |
||
| 491 | |||
| 492 | 1 | Tatsuya ISHIGAKI | ## 13.6 画像を扱う Pillow |
| 493 | 2 | Tatsuya ISHIGAKI | 画像データ (JPEG, PNG など) を扱う機能 (拡大縮小、回転、色調変更、文字挿入 等) を提供する |
| 494 | `pip install pillow` |
||
| 495 | `import PIL` ※インポート時の指定に注意 |
||
| 496 | |||
| 497 | - 画像読み込み (PIL.Image モジュール) |
||
| 498 | - 関数 `open(file_path, mode='r', formats=None)` |
||
| 499 | - `file_path` 画像ファイルパス |
||
| 500 | - `mode` モード指定だが、'r' 以外は使用できない |
||
| 501 | - `formats` 開くファイルのフォーマットを制限したい場合は、フォーマットをタプルかリストで指定 |
||
| 502 | - **戻り値** `Image` オブジェクト |
||
| 503 | - 画像のサイズを変更する、回転する |
||
| 504 | - メソッド `resize(size, resample=None, box=None, reducing_gap=None)` |
||
| 505 | - `size` リサイズ後の画像サイズ (ピクセル) をタプル (width, hight) で指定 |
||
| 506 | - `resample` リサンプリングフィルターを指定 |
||
| 507 | - `PIL.Image.NEAREST` 最近傍 |
||
| 508 | - `PIL.Image.BILINEAR` バイリニア |
||
| 509 | - `PIL.Image.BICUBIC` バイキュービック |
||
| 510 | - `PIL.Image.LANCZOS` ランチョス |
||
| 511 | - `PIL.Image.BOX` |
||
| 512 | - `PIL.Image.HAMMING` |
||
| 513 | - **戻り値** `Image` オブジェクト |
||
| 514 | - メソッド `rotate(angle, resample=0, expand=0, center=None, translate=None, fillcolor=None)` |
||
| 515 | - `angle` 回転角度 (反時計回り) |
||
| 516 | - **戻り値** `Image` オブジェクト |
||
| 517 | - 画像を保存する |
||
| 518 | - メソッド `save(file_path, format=None, **params)` |
||
| 519 | - `file_path` 保存ファイルパス |
||
| 520 | - `format` 保存する画像のフォーマットを指定 (省略時は `file_path` の拡張子から自動判別) |
||
| 521 | - `**param` フォーマットごとに異なるオプション指定 |
||
| 522 | - **戻り値** None |
||
| 523 | - テキストの埋め込み |
||
| 524 | - `ImageFont.truetype()` でフォントオブジェクト (FreeTypeFont) を取得し、`ImageDraw.Draw()` で `Image` に対する `ImageDraw` オブジェクトを作成し、`ImageDraw.text()` で画像に埋め込む |
||
| 525 | - 関数 `ImageFont.truetype(font=None, size=10, index=0, encoding='', layout_engine=None)` |
||
| 526 | - `font` TrueType のフォントファイルを設定 |
||
| 527 | - `size` フォントサイズを指定 |
||
| 528 | - `index` 指定したフォントファイルに複数んおフォントが含まれている場合、ttc 番号を指定 |
||
| 529 | - **戻り値** フォントオブジェクト (`FreeTypeFont`) |
||
| 530 | - 関数 `ImageDraw.Draw(im, mode=None)` |
||
| 531 | - `im` Image オブジェクト |
||
| 532 | - **戻り値** `ImageDraw` オブジェクト |
||
| 533 | - メソッド `ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=4, align='left', direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False)` |
||
| 534 | - `xy` テキストを埋め込む座標をタプル (x, y) で指定 (`anchor` 指定で実位置に変化あり) |
||
| 535 | - `text` 埋め込むテキスト |
||
| 536 | - `fill` テキストの色指定 |
||
| 537 | - `font` フォントオブジェクトを指定 |
||
| 538 | - **戻り値** None |
||
| 539 | |||
| 540 | ```python |
||
| 541 | >>> from PIL import Image, ImageDraw, ImageFont |
||
| 542 | >>> ifont = ImageFont.truetype(r'C:\Windows\Fonts\Meiryo UI\meiryo.ttc', size=40) |
||
| 543 | >>> image = Image.open("GrandCanyon.jpg") |
||
| 544 | >>> idraw = ImageDraw.Draw(image) |
||
| 545 | >>> idraw.text((306,10), "グランドキャニオン", font=ifont, fill='red') |
||
| 546 | >>> image.save('GrandCanyon_withText.jpg') |
||
| 547 | ``` |
||
| 548 | |||
| 549 | <br>元画像 |
||
| 550 |  |
||
| 551 | |||
| 552 | <br>テキスト埋め込み後画像 |
||
| 553 |  |