12章学習記録 » 履歴 » リビジョン 2
リビジョン 1 (Tatsuya ISHIGAKI, 2025/07/25 03:03) → リビジョン 2/4 (Tatsuya ISHIGAKI, 2025/07/25 07:45)
## 12.3 tar ファイルを扱う tarfile
gzip, bz2, lzma 形式で圧縮されたものを含む、tar 形式アーカイブを読み書きする
- tar ファイルを操作する
- 関数 `open(name=None, mode='r', fileobj=None, bufsize=20240, **kwargs)`
- `name` tar ファイルのファイル名
- `mode` モード指定 `r` `w` 等
- 圧縮形式を指定する場合は `r:gz` `w:xz` 等 (非圧縮指定は `w:` 等)
- 読み込み時は `r` だけでも、ファイル名拡張子から圧縮形式が自動判定される
- 圧縮ファイルは追記モードが使用できない (`a` `a:` のみ)
- `fileobj` tar ファイルのファイルオブジェクト
- `bufsize` ブロックサイズ (デフォルトでよい)
- **戻り値** `tarfile.TarFile`
- 関数 `is_tarfile(name)`
- `name` ファイル名、または file-like オブジェクト
- **戻り値** (bool) 指定ファイルが tar 形式アーカイブなら True
- `TarFile` オブジェクトのメソッド
|メソッド名|解説|戻り値|
|---|---|---|
|`getnames()`|tar ファイル内にアーカイブされているファイル名リスト|list|
|`getmember(name)`|指定ファイル名の `TarInfo` を返す|TarInfo|
|`getmembers()`|tar ファイル内にアーカイブされている全ファイルの `TarFile` のリストを返す|list|
|`extract(member, path="", set_attrs=True, *, numeric_owner=False)`|指定ファイルを指定場所へ展開<br>`member`:ファイル名または`TarInfo`|None|
|`extractall(path="", set_attrs=True, *, numeric_owner=False)`|全ファイルを指定場所へ展開|None|
|`extractfile(member)`|指定ファイルを開き、ファイルオブジェクトを返す<br>`member`:ファイル名または`TarInfo`|ファイルオブジェクト|
|`add(name, arcname=None, recursive=True, exclude=None, *, filter=None)`|指定ファイルを tar ファイルのアーカイブへ追加する<br>`arcname`を指定するとそのファイル名で追加<br>ディレクトリ指定では再帰追加可能|?|
|`close()`||None|
```python
>>> import tarfile
>>> with tarfile.open("./testarchive.tar", "w:gz") as f:
... f.add("./inArchive1.txt")
...
>>> with tarfile.open("./testarchive.tar") as f:
... f.getnames()
... f.getmembers()
...
['./inArchive1.txt']
[<TarInfo './inArchive1.txt' at 0x140b4104640>]
>>> with tarfile.open("./testarchive.tar") as f:
... with f.extractfile("./inArchive1.txt") as elem:
... elem.read().decode("sjis")
...
'アーカイブ内ファイル1'
>>> with tarfile.open("./testarchive.tar") as f:
... info = f.getmember("./inArchive1.txt")
... info
... print(f"{info.name=}, {info.size=}, {info.mtime=}, {info.mode=:o}")
...
<TarInfo './inArchive1.txt' at 0x140b4104940>
info.name='./inArchive1.txt', info.size=22, info.mtime=1753410842.0, info.mode=666
>>> with tarfile.open("./testarchive.tar") as f:
```
## 12.4 Python オブジェクトをシリアライズする pickle
Python オブジェクトをファイル等に保存可能なバイト列に変換 (**pickle 化** という)、復元 (**非 pickle 化** という) する
- JSON へのシリアライズ方法である json モジュールとの比較
- JSON は文字列だが、pickle はバイナリ
- JSON は他のプログラミング言語でも利用可能だが、pickle は Python 固有フォーマット
- JSON は文字列、数値など一部のデータ型のみ扱うが、pickle は Python の様々なオブジェクトを扱える
- Python オブジェクトのシリアライズとデシリアライズ
|関数名|解説|戻り値|
|---|---|---|
|`dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)`|オブジェクトをシリアライズしてファイルへ保存する|None|
|`dumps(obj, protocol=None, *, fix_import=True, buffer_callback=None)`|オブジェクトをシリアライズしてバイト列を返す|bytes|
|`load(file, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)`|ファイルの中身をデシリアライズし、結果オブジェクトを返す|object|
|`loads(data, /, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)`|バイト列をデシリアライズし、結果オブジェクトを返す|object|
dumps, loads (bytes でのやり取り) の例
```python
>>> import pickle
>>> from datetime import datetime
>>> now = datetime.now()
>>> data = {"NOW-date": now} # 値が datetime の辞書データ作成
>>> type(data)
<class 'dict'>
>>> data
{'NOW-date': datetime.datetime(2025, 7, 25, 16, 4, 0, 201811)}
>>> serialized = pickle.dumps(data) # シリアライズ
>>> serialized
b'\x80\x04\x958\x00\x00\x00\x00\x00\x00\x00}\x94\x8c\x08NOW-date\x94\x8c\x08datetime\x94\x8c\x08datetime\x94\x93\x94C\n\x07\xe9\x07\x19\x10\x04\x00\x03\x14S\x94\x85\x94R\x94s.'
>>> desirialized = pickle.loads(serialized) # デシリアライズ
>>> type(desirialized)
<class 'dict'>
>>> desirialized # 元のデータを復元できている
{'NOW-date': datetime.datetime(2025, 7, 25, 16, 4, 0, 201811)}
```
dump, load (ファイルでのやり取り) の例
```python
>>> data # 対象データ
{'NOW-date': datetime.datetime(2025, 7, 25, 16, 4, 0, 201811)}
>>> with open("nowdate.pkl", "wb") as f:
... pickle.dump(data, f) # シリアライズしてファイルへ書き込み
...
>>> with open("nowdate.pkl", "rb") as f:
... obj = pickle.load(f) # ファイル内容をデシリアライズ
...
>>> obj # 復元を確認
{'NOW-date': datetime.datetime(2025, 7, 25, 16, 4, 0, 201811)}
```
`dump()` で生成されたファイルの様子

- ※ pickle 化にはプロトコルのバージョンが 0 から 5 まであり、新しいバージョンで pickle 化されたオブジェクトは古いバージョンで非 pickle 化できない (`pickle.DEFAULT_PROTOCOL` でデフォルト確認可能)