2024年版 Python標準ライブラリ完全網羅ガイド


# はじめに
この記事は[Nuco Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nuco)の23日目の記事です。
　　　　
Pythonの標準ライブラリについて全てまとめた記事になります！

標準ライブラリでちゃんとサポートされているのに、サードパーティのものを利用してしまっていたり、自分で車輪の再発明をしてしまったという経験をお持ちの方もいると思います。
    　　　　
Pythonも幾度のバージョンアップによって、標準に組み込まれた機能も増えてもきました。
全てを暗記する必要も全くありませんが、どんなことができるのかを頭の中に入れておくだけで、来年からのPython生活の選択肢が広がることと思います！
　　　　
1つ1つ解説したことで、相当なボリュームになってしましたので、いいねやストックをして何回かに分けてお楽しみください。
　　　　
本記事が少しでも皆様のお役に立てば幸いです！

:::note info
弊社Nucoでは、他にも様々なお役立ち記事を公開しています。よかったら、Organizationのページも覗いてみてください。
また、Nucoでは一緒に働く仲間も募集しています！興味をお持ちいただける方は、[こちら](https://recruit.nuco.co.jp/?qiita_item_id=0873a5f286049ba46265)まで。
:::

# ライブラリ一覧

## 1. テキスト処理サービス
   - ### 1-1 `string` --- 一般的な文字列操作

  `string` モジュールは、文字列操作をシンプルに行える便利な機能が集約されたモジュールです。このモジュールには、英数字や特殊文字の定数が定義されており、さまざまな文字列操作を効率的に行うことができます。

   #### 主な機能
   - **`ascii_letters`**: 全てのアルファベット文字 (大文字および小文字)。
   - **`digits`**: 数字 (`0123456789`) のみ。
   - **`punctuation`**: 一般的な句読点 (`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`)。
   - **`whitespace`**: 空白文字 (`' \t\n\r\x0b\x0c'`)。

   #### 利用例
   `string.ascii_letters` を使えば、英字の文字列を簡単に取得できるため、ランダムな文字列生成などに活用できます。

   ```python
   import string
   import random

   # ランダムな英字のみの文字列を生成
   random_string = ''.join(random.choice(string.ascii_letters) for _ in range(10))
   print(random_string) 
   # ZkFgHpDqTj  # ランダムに生成された英字の文字列（実行のたびに異なります）
   ```
<br><br>  
  - ### 1-2 `re` --- 正規表現操作

   Pythonの`re`モジュールは、正規表現（regex）を使った高度な文字列操作を提供します。正規表現を使うことで、文字列パターンの検索、置換、分割、マッチングなどを効率的に実行できます。`re`モジュールは、複雑な文字列処理を簡潔に記述できるため、特にパターンマッチングや検証が必要な場面で有用です。

   #### 主な機能

   - **`match(pattern, string)`**: 
文字列の先頭が指定したパターンと一致するかをチェックします。一致すればmatchオブジェクトを返し、一致しなければNoneを返します。
　　　　
   - **`search(pattern, string)`**: 
文字列全体を対象に、最初に一致するパターンを検索します。見つかればmatchオブジェクトを返し、見つからなければNoneを返します。
　　　　
   - **`findall(pattern, string)`** :
文字列内でパターンに一致するすべての部分をリストとして返します。
　　　　
   - **`finditer(pattern, string)`**:  パターンに一致するすべての部分をmatchオブジェクトのイテレータとして返します。
　　　　
   - **`sub(pattern, repl, string)`**:  
   文字列内のパターンに一致する部分を指定した文字列（repl）で置換します。
　　　　
  
  - **`split(pattern, string)`**:  
  パターンに一致する部分で文字列を分割し、リストとして返します。


:::note info
   #### 主なパターン
   - **`\d`**: 数字（0123456789）のいずれかに一致します。
   - **`\w`**:  英字（大文字および小文字）、数字、アンダースコア（_）に一致します。
   - **`\s`**: 空白文字（空白、タブ、改行など）に一致します。
   - **`^`**: 文字列の先頭に一致します。
   - **`$`**: 文字列の末尾に一致します。
:::

#### 利用例
`re`モジュールを使えば、文字列のパターンマッチングや操作が簡単に行えます。

   ```python
   import re

    text = "The price is 1000 dollars and 50 cents."

    # 文字列から数字のみを抽出
    numbers = re.findall(r'\d+', text)

    print(numbers)  # 出力: ['1000', '50']
   ```

<br><br>
  - ### 1-3 `difflib` --- 差分計算の補助
      Pythonの`difflib`モジュールは、2つの文字列やリストの差分を計算し、どの部分が異なっているかを確認するための便利な機能を提供します。特に、2つの文字列がどのように異なるかを比較したり、変更点をハイライトしたりするのに使います。

   #### 主な機能
   - **`difflib.SequenceMatcher()`**:
   2つのシーケンス（文字列、リストなど）の間で最長一致部分や差分を計算します。類似度を計算するためにも使用され、差分や変更箇所の情報を取得できます。
   　　　　
   - **`difflib.ndiff`**: 
   2つのシーケンスの差分を生成し、差分を示す文字列（+や-）で出力します。通常、テキストファイルの変更点を比較する際に使われます。
　　　　
- **`SequenceMatcher(isjunk, a, b)`**:
2つのシーケンスaとbを比較し、その類似度や差分を計算します。isjunkはオプションの引数(初期値はNone)で、比較時の無視すべき要素をカスタマイズできます。
　　　　
- **`ndiff(a, b)`**:
2つのシーケンスaとbの差分を比較し、その結果をリストとして出力します。変更部分が+や-の記号で表示されます。
  
     #### 利用例
   `diffib`モジュールを使えば、文字列のどの部分が一致し、どこが異なるかが分かります。

   ```python
   import difflib

    # 2つの文字列
    text1 = "Hello world!"
    text2 = "Hello worlD!"

    # SequenceMatcherを使って差分を比較
    #(無視すべき要素,比較する１つ目のシーケンス,比較する2つ目のシーケンス)
    matcher=difflib.SequenceMatcher(None, text1, text2)

    # 差分を取得
    diff = matcher.get_opcodes()
    print(diff)
    #[('equal', 0, 6, 0, 6), ('equal', 6, 11, 6, 11), ('replace', 11, 12, 11, 12)]

   ```

<br><br>
   - ### 1-4 `textwrap` --- テキストの折り返しと埋め込み
`textwrap` モジュールは、テキストを折り返す（行の長さを調整する）ことや、埋め込み（インデントや改行を適切に挿入する）を効率的に行うためのツールが提供されているモジュールです。このモジュールを使うことで、長い文字列を読みやすい形式に整形したり、テキストを整えたりすることができます。

  #### 主な機能

  
 - **`textwrap.fill(text, width, replace_whitespace, drop_whitespace, initial_indent, subsequent_indent, expand_tabs, tabsize)`**: 
 長い文字列を指定した幅で折り返して整形します。
　　　　
  - **`textwrap.wrap(text, width, replace_whitespace, drop_whitespace, initial_indent, subsequent_indent, expand_tabs, tabsize )`**：
  `fill()`と似ていますが、折り返し後の行をリストとして返します。
　　　　
  -  **`textwrap.shorten(a, i, j)`**:文字列を指定した最大長に短縮し、省略記号`...`を追加します。
 　　　　
-  **`textwrap.indent(a, i,j)`**:各行に指定したインデントを追加します。
  　　　　
  -  **`textwrap.dedent(a)`**:各行の先頭のインデントを削除します。


#### 利用例
`textwrap`モジュールは、文章やテキストを見やすく整形するために非常に役立つツールです。
    
```python
import textwrap

# 長い文字列
long_text = "Python is an amazing programming language that can be used for a wide variety of applications, including web development, data analysis, artificial intelligence, and more."

# 指定した幅で折り返して整形
wrapped_text = textwrap.fill(long_text, width=50)

print(wrapped_text)
```



  出力
```
Python is an amazing programming language that can
be used for a wide variety of applications, including
web development, data analysis, artificial
intelligence, and more.
```

<br><br>
  -  ### 1-5  `unicodedata` --- Unicode データベース
      
Pythonの`unicodedata`モジュールは、Unicode文字：(異なる言語や文化圏の文字を一つのシステムで扱えるようにするための文字コード)　に関する情報を取得したり、文字のプロパティを操作するための便利な機能を提供します。特に文字のカテゴリや名前、正規化などを簡単に処理できます。
  
  #### 主な機能
 - **`unicodedata.name(char)`**:文字に対応するUnicode名を取得します。
 　　　　　
 - **`unicodedata.category(char)`**:
 文字のカテゴリ（例えば、アルファベット、数字、記号など）を取得します。
 　　　　
 - **`unicodedata.normarize(form, str)`**:
 Unicode文字列の正規化を行い、異なる表現を統一します。
 　　　　
 - **`unicodedata.combining(char)`**:
 指定した Unicode キャラクターが「結合可能な」文字かどうかを判定するために使われます


#### 利用例

```python
import unicodedata

# 文字 'A' の Unicode 名を取得
char_name = unicodedata.name('A')
print(char_name)
# LATIN CAPITAL LETTER A
```



<br><br>
  - ### 　1-6 `stringprep` --- インターネットの文字列調製

Pythonの`stringprep`モジュールは、インターネット上で使用する文字列（特にユーザー名、ドメイン名、パスワードなど）の準備や正規化を行うためのツールです。

:::note info
異なるシステム間で文字列が一貫した形式で扱えるようになります。特に、Unicode文字をIDNA（国際化ドメイン名）やその他のインターネット標準に適合させるために使用されます。
:::

### 主な機能

 - **`stringprep.in_table_b1(code)`** :変換せずにそのまま使用できる文字（コードポイント）かどうかを判定します。Unicode 3.2の規格に基づいて評価されます。

 - **`stringprep.in_table_c21(code)`** :ASCIIの制御文字（C0制御文字）かどうかを判定します。これらの文字は多くのプロトコルで禁止されています。

 - **`stringprep.in_table_d1(code)`** :双方向（Bidirectional）文字のうち、右から左（RtoL）に表示される文字かどうかを判定します。主にアラビア語やヘブライ語などの文字を識別します。

 - **`stringprep.map_table_b2(code)`** :大文字を小文字に変換します。この関数は文字列の正規化において、大文字小文字の違いを統一する際に使用されます。

 - **`stringprep.in_table_c12(code)`** :非ASCII空白文字かどうかを判定します。これには全角スペースなどの特殊な空白文字が含まれます。プロトコルによっては、これらの文字の使用が制限される場合があります。

  #### 利用例
```python
import stringprep

def convert_to_lowercase():
   text = "Hello WORLD"
   converted = ''.join(stringprep.map_table_b2(char) for char in text)
   print(f"元の文字列: {text}")
   print(f"変換後: {converted}")

convert_to_lowercase()
# 元の文字列: Hello WORLD
# 変換後: hello world

# 基本的な使用例
def check_nonascii_spaces():
   # 通常の空白と全角空白を含むテキスト
   texts = ["Hello World", "Hello　World"]  # 2番目は全角空白を使用
   for text in texts:
       has_nonascii_space = any(stringprep.in_table_c12(char) for char in text)
       print(f"'{text}' は非ASCII空白を{'含みます' if has_nonascii_space else '含みません'}")

check_nonascii_spaces()
# 'Hello World' は非ASCII空白を含みません
# 'Hello　World' は非ASCII空白を含みます
```


 <br><br>
 
   -  ### 1-7  `readline` --- GNU readline のインターフェース
`readline`モジュールは、GNU Readlineライブラリのインターフェースを提供し、インタラクティブなコマンドライン環境で文字列入力を管理するために使用されます。このモジュールは、コマンドラインの編集、履歴管理、補完機能などをサポートしており、特に対話的なPythonシェルやコマンドラインアプリケーションで便利です。

#### 主な機能

- **`readline.get_history_item(index)`**:
履歴リストから指定されたインデックス位置のコマンドを取得します。
　　　　
- **`readline.add_history(line)`**:入力された行（line）を履歴に追加します。
　　　　
- **`readline.clear_history(index)`**:履歴をクリアします。
　　　　
- **`readline.set_startup_hook(コールバック関数, 引数)`**:
起動時にコマンドを実行するためのフックを設定します。
　　
- **`readline.set_completer(補完関数)`**:補完を行う関数を設定します。
　　　　
- **`readline.parse_and_bind(キー: 動作)`**:
特定のキーのバインディングを設定します（例: Tabキーで補完を呼び出す）。
　　　　
- **`readline.set_completer_delims()`**:
補完対象として認識される区切り文字を変更します。
　　　　　　　
- **`readline.set_history_length()`**:履歴の最大数を設定します。

#### 利用例
```python
import readline
import os
import atexit

# 履歴ファイル設定
history_file = os.path.expanduser("~/.my_shell_history")

if os.path.exists(history_file):
    readline.read_history_file(history_file)

atexit.register(lambda: readline.write_history_file(history_file))

# 補完対象
commands = ["list", "show", "exit", "help", "restart"]

def completer(text, state):
    options = [cmd for cmd in commands if cmd.startswith(text)]
    return options[state] if state < len(options) else None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

# インタラクティブシェル
print("Welcome to the shell! Type 'exit' to quit.")
while True:
    try:
        line = input(">> ")
        if line.strip() == "exit":
            break
        print(f"You entered: {line}")
    except (KeyboardInterrupt, EOFError):
        print("\nExiting...")
        break
```

<br><br>
- ### 1-8 `rlcompleter` --- GNU readline の補完機能
`rlcompleter`は、GNU Readline ライブラリを使用した補完機能を提供するモジュールです。

Python のインタラクティブシェルやコマンドラインインターフェース（CLI）でのコード補完をサポートします。これにより、変数名、関数名、モジュール名、オブジェクトの属性（ドット補完）などを補完でき、コード入力を効率的に行うことができます。

 #### 主な機能
- **`rlcompleter.Completer(namespace=None)`**:
このクラスは、補完機能を提供します。ユーザーが補完する対象を指定したり、補完候補をリストアップしたりできます。`namespace` 引数は、補完対象となる変数や関数が格納されている名前空間を指定します。デフォルトでは、globals()（グローバル名前空間）を使用しますが、必要に応じて他の名前空間を指定することもできます。
　　　　
- **`readline.set_completer(補完関数)`**:
この関数を使用することで、補完機能をカスタマイズすることができます。
　　　　
- **`readline.parse_and_bind(キー: アクション)`**:
補完の動作を定義するために、ショートカットキーや補完モードを設定できます。

#### 利用例
```python
import readline
import rlcompleter
import atexit
import os

# 履歴ファイルの設定
history_file = os.path.expanduser("~/.python_shell_history")

# 履歴ファイルの読み込み
if os.path.exists(history_file):
    readline.read_history_file(history_file)

# 履歴を保存する設定
atexit.register(lambda: readline.write_history_file(history_file))

# rlcompleter を使った補完機能の設定
readline.set_completer(rlcompleter.Completer().complete)
readline.parse_and_bind("tab: complete")  # Tab キーで補完

# インタラクティブシェル
print("Welcome to the rlcompleter-powered shell! Type 'exit' to quit.")
while True:
    try:
        # 入力を受け付け
        user_input = input(">> ")
        if user_input.strip() == "exit":
            print("Exiting...")
            break
        # 入力を評価して結果を表示
        result = eval(user_input)
        print(f"Result: {result}")
    except Exception as e:
        print(f"Error: {e}")
```

## 2. バイナリデータ処理
   - ### 2-1 `struct` --- バイト列をパックされたバイナリデータとして解釈
Python の `struct` モジュールは、C 言語の struct と似た機能を提供し、バイナリデータ（バイト列）を効率的にパック（組み立て）したりアンパック（解体）したりするためのツールです。特に、ネットワークプロトコルやファイルフォーマットなどで扱うバイナリデータを Python で操作する際に便利です。

`struct` モジュールを使うことで、データを指定したフォーマットに基づいてバイナリ形式で変換（エンコード）したり、バイナリデータから元の値を抽出（デコード）することができます。

#### 主な機能
 - **`pack(format, v1, v2, ...)`**:指定したフォーマットに従って、引数 v1, v2, ... をバイナリ形式にパックして返します。
 　　　　
 - **`unpack(format, buffer)`**:バイナリデータ（buffer）を指定したフォーマットでアンパックして、元のデータに戻します。
 　　　　
 - **`バイナリデータを直接操作するためのフォーマット文字列`**:`struct`モジュールは、データ型のフォーマットを指定するために文字列を使います。フォーマット文字列は、各データ型のバイト数やエンディアン（バイトオーダー）を指定するために使用されます。
`b` : 1バイトの符号付き整数
`B` : 1バイトの符号なし整数
`h` : 2バイトの符号付き整数
`H` : 2バイトの符号なし整数
`i` : 4バイトの符号付き整数
`I` : 4バイトの符号なし整数
`f` : 4バイトの浮動小数点数
`d` : 8バイトの浮動小数点数
`s` : 文字列（指定された長さのバイト列）
`x` : 1バイトのパディング（ダミーバイト）

#### 利用例
 ```python
 import struct

# 整数、浮動小数点、文字列をパック
packed_data = struct.pack('I f 5s', 1, 3.14, b'Hello')

# パックしたデータを表示（バイナリ形式）
print(packed_data)  # 出力例: b'\x01\x00\x00\x00\xcd\xcc\x0c@Hello'
```

ここで、'I f 5s' は次のように解釈されます：

`'I'` : 4バイトの符号なし整数（1）
`'f'` : 4バイトの浮動小数点数（3.14）
`'5s'` : 5バイトの文字列（b'Hello'）

<br><br>
- ### 2-2 `codecs` --- codec レジストリと基底クラス
Python の`codecs`ジュールは、文字エンコーディングに関連する操作をサポートしており、テキストデータを異なるエンコーディングで読み書きしたり、エンコーディングとデコーディングを行うための便利なツールを提供します。特に、Unicode 文字列とバイト列の相互変換や、ファイルの読み書き時のエンコーディング指定に役立ちます。

#### 主な機能
- **`codecs.open(<ファイル名>, <モード>, <エンコーディング>, <エラー処理>, <バッファサイズ>)`**:
 ファイルを指定したエンコーディングで開くために使います。これにより、ファイルの読み書き時に文字エンコーディングを明示的に指定できるので、Unicode 文字列の読み書きが簡単になります。

- **`codecs.encode(<データ>, <エンコーディング>, <エラー処理>)`**:
文字列を指定したエンコーディングでバイト列にエンコードする。
　　　　
- **`codecs.decode(<データ>, <エンコーディング>, <エラー処理>)`**:
バイト列を指定したエンコーディングでデコードして文字列に変換する

#### 利用例
 ```python
 import codecs

# 文字列を UTF-8 でエンコード
text = "こんにちは、世界！"
encoded_text = codecs.encode(text, 'utf-8')
print(encoded_text)  # バイト列として表示
#出力:
b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf\xe3\x80\x81\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'

# バイト列をデコードして文字列に戻す
decoded_text = codecs.decode(encoded_text, 'utf-8')
print(decoded_text)  # 元の文字列に戻る
#出力:こんにちは、世界！
```
上記の例では、まず文字列 "こんにちは、世界！" を UTF-8 エンコーディングでエンコードし、その後バイト列をデコードして元の文字列に戻しています。

## 3. データ型
- ### 3-1 `datetime` --- 日付と時間
pythonの`datetime`モジュールは、日付や時刻を扱うための強力なツールを提供しています。このモジュールを使用すると、日付や時刻の操作（加算、減算、比較など）やフォーマット（文字列として表示）を簡単に行うことができます。また、時間帯（タイムゾーン）の管理にも対応しています。

#### 主な機能

- **`datetime`**:日付と時刻を表すクラス。
　　　　
- **`date`**:日付と時刻を表すクラス。
　　　　
- **`time`**:時刻（時、分、秒、マイクロ秒）を表すクラス。
　　　　
- **`timedelta`**: 時間の差を表すクラス（加算や減算に使う）。
　　　　
- **`tzinfo`**:タイムゾーン関連の情報を扱うための基底クラス。

#### 利用例
```python
    import datetime

    # 現在の日時を取得
    now = datetime.datetime.now()
    print(now)  # 例: 2024-11-29 14:35:42.123456
```

<br><br>
- ### 3-2 `zoneinfo` --- タイムゾーンサポート

`zoneinfo`は、Python 3.9 以降で追加された標準ライブラリで、タイムゾーン情報を管理するためのクラスと機能を提供します。タイムゾーンのオフセットや夏時間（DST）などを正確に扱うために使用されます。

:::note info
従来、Pythonでタイムゾーンを扱うには、`pytz` ライブラリを外部でインストールして使用する必要がありましたが、`zoneinfo` モジュールが追加されたことで、外部ライブラリを使わずに標準ライブラリでタイムゾーンを取り扱うことができるようになりました。
:::


#### 主な機能
`Zoneinfo`クラスを使用して、タイムゾーン付きの `datetime` オブジェクトを作成したり、異なるタイムゾーン間で日時を変換したりすることができます。タイムゾーンの取り扱いを簡潔にし、より正確で信頼性の高い日時計算を行うための強力なツールです。

#### 利用例
```python
import datetime
import zoneinfo

# タイムゾーンを指定（例: "Asia/Tokyo"）
tokyo_tz = zoneinfo.ZoneInfo("Asia/Tokyo")

# 現在の日時をタイムゾーン情報付きで取得
now_in_tokyo = datetime.datetime.now(tokyo_tz)
print(now_in_tokyo)  # 例: 2024-11-29 14:35:42+09:00
```
上記のコードでは、Asia/Tokyo タイムゾーンの現在の日時が取得され、タイムゾーンオフセット（+09:00)：協定世界時（からの時間差を示すもの)が表示されます。

<br><br>
  - ### 3-3 `calendar` --- カレンダー関連機能
Python の `calendar` モジュールは、日付や曜日に関連する操作を行うための便利なツールを提供します。カレンダーの表示、曜日の計算、月ごとのカレンダーを生成したり、指定した年や月の日付情報を取得したりすることができます。

#### 主な機能
- **`カレンダーの表示`** - : 特定の年や月のカレンダーを表示することができます。
- **`曜日の計算`** -  :  指定した日付の曜日を計算したり、曜日の名前を取得したりできます。
- **`祝日や特定の日付の計算`** -  :  祝日や特定の日付の曜日や情報を取得することができます。

#### 利用例 1
```python
import calendar

# 2024年5月のカレンダーを表示
print(calendar.month(2024, 5))
```
出力例 1
```css
     May 2024
Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
```

 利用例 2
```python
import calendar

# 2024年の年間カレンダーを表示
print(calendar.calendar(2024))
```

 出力例 2
```css                                  2024
      January                   February                   March
Mo Tu We Th Fr Sa Su       Mo Tu We Th Fr Sa Su       Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7         1  2  3  4  5  6  7         1  2  3  4  5  6
 8  9 10 11 12 13 14         8  9 10 11 12 13 14         7  8  9 10 11 12 13
14 15 16 17 18 19 20        15 16 17 18 19 20 21        14 15 16 17 18 19 20
21 22 23 24 25 26 27        22 23 24 25 26 27 28        21 22 23 24 25 26 27
28 29 30 31                 29                         28 29 30 31

      April                        May                        June
Mo Tu We Th Fr Sa Su       Mo Tu We Th Fr Sa Su       Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7         1  2  3  4  5  6  7         1  2  3  4  5  6
 8  9 10 11 12 13 14         8  9 10 11 12 13 14         7  8  9 10 11 12 13
15 16 17 18 19 20 21        15 16 17 18 19 20 21        14 15 16 17 18 19 20
22 23 24 25 26 27 28        22 23 24 25 26 27 28        21 22 23 24 25 26 27
29 30                       29 30 31                  28 29 30
```


<br><br>
- ### 3-4 `collections` --- コンテナデータ型
`collections`は、効率的で便利なデータ構造を提供するモジュールです。通常のリストや辞書では扱いにくい特別なデータ構造が含まれており、さまざまな場面で便利に使えるものがたくさんあります。

 #### 主な機能
- **`Counter(iterable_or_mapping)`**  : 要素のカウント。
- **`defaultdict(default_factory, initial_data)`**: デフォルト値を持つ辞書。
`default_factory`: キーが存在しない場合に返されるデフォルト値を生成する関数やクラス。
`initial_data`: 初期データ（任意）。最初から追加されるキーと値のペアを指定できる。
- **`OrderedDict(<initial_data>)`**: 順序付きの辞書。
- **`deque(iterable, maxlen)`**: 両端キュー（高速な挿入と削除）。
指定された長さを超える要素が追加されると、先頭の要素が削除されます（FIFO）。
- **`ChainMap(mappings)`**: 複数の辞書をまとめて扱う。
mappings: 複数の辞書やマッピング（任意）。これらをまとめて一つのビューとして扱います。複数の辞書を順番に検索でき、最初に見つかったキーに対応する値が返されます。

#### 利用例
```python
from collections import Counter

# 文字列内で単語の出現頻度をカウント
text = "apple orange apple banana apple orange orange"
word_count = Counter(text.split())

print(word_count)  # 出力: Counter({'apple': 3, 'orange': 3, 'banana': 1})
```
この例では、`Counter`を使って、文字列内の単語の出現頻度をカウントしています。`text.split()`で文字列を単語に分割し、`Counter`でそれぞれの単語が何回出現したかを集計しています。

また、defaultdictの利用例も紹介します。

```python
from collections import defaultdict

text = "apple orange apple banana apple orange orange"

# defaultdictを使って、キーが存在しない場合にデフォルト値を設定
count_dict = defaultdict(int)

for word in text.split():
    count_dict[word] += 1

print(count_dict)  # 出力: defaultdict(<class 'int'>, {'apple': 3, 'orange': 3, 'banana': 1})
```
この例では、`defaultdict(int)`を使い、`int（0）`をデフォルト値として指定しています。これにより、キーが存在しない場合に自動的に0からカウントが始まります。



<br><br>  
  - ### 3-5 `collections.abc` --- コンテナの抽象基底クラス
 `collections.abc`は、抽象基底クラス（ABC: Abstract Base Classes）を提供します。このモジュールは、コレクション型（リスト、セット、辞書など）のインターフェースを定義するクラスを含んでおり、これらのインターフェースに従って動作するカスタムコレクションを作成したり、コレクション型が特定のインターフェースを実装しているかどうかをチェックするために利用できます。

#### 主な機能
- **`Iterable`**:反復可能なオブジェクト（for ループで繰り返し処理ができるオブジェクト）を定義するためのクラスです。
- **`Container`**:Container は、in 演算子を使って要素が含まれているかどうかを確認できるオブジェクトを定義します。通常のリストやセット、辞書がこのクラスを実装しています。
- **`Sequence`**:インデックスでアクセスできるオブジェクトを定義するクラスです。リストやタプルがこのクラスを実装しており、`__getitem__()`, `__len__()` メソッドを持ちます。
- **`MutableSequence`**:Sequence と同じインターフェースを持つが、要素の変更（挿入、削除）が可能であることが要求されます。list はこのクラスを実装しています。
- **`Set`**:順序なしのコレクションで、重複しない要素の集まりを持つオブジェクトを定義するクラスです。set や frozenset がこのクラスを実装しています。
- **`MutableSet`**:Set と同じインターフェースを持つが、要素の追加や削除が可能であることが要求されます。set はこのクラスを実装しています。
 
 
 
 #### 利用例
 ```python
from collections.abc import Iterable

# リストはIterableである
print(isinstance([1, 2, 3], Iterable))  # True

# 数字はIterableではない
print(isinstance(123, Iterable))  # False
```

<br><br>
- ### 3-6 `heapq` --- ヒープキューアルゴリズム
`heapq`は、ヒープキューアルゴリズムを使用して優先度付きキュー（priority queue）を効率的に実装するためのツールです。このモジュールは、最小ヒープ（Min-Heap）を基盤として、要素の追加や削除を高速に行うことができ、特に最小値や最大値の取得を効率的に行うことができます。
 
#### 主な機能 
- **`heapq.heappush(heap, item) `** : 
要素の追加、ヒープに新しい要素を追加します。ヒープの特性を保ちながら追加されます。
    　　　　　　　　

- **`heapq.heappop(heap)`** : 
最小値の削除と取得、ヒープの最小値を取り出して削除します。
　　　　

- **`heapq.heapreplace(heap, item)`** : 
最小値の削除と新しい要素の挿入します。最小値を削除してから新しい値を追加する heappop() と heappush() を実行するよりも効率的です。
　　　　

- **`heapq.nlargest(n, iterable, key=None)`** :
 n 個の最大値を取得、iterable から最も大きい n 個の要素を取得します。key 引数を使用して比較基準を指定することもできます。
　　　　

- **`heapq.heapify(iterable)`** : 
任意のリストをヒープに変換します。iterable はリストである必要があります。




#### 利用例

```python
import heapq

def task_scheduler():
    # タスクとその優先度を管理するヒープ
    tasks = []
    
    # タスクの追加 (優先度, タスク名)
    heapq.heappush(tasks, (2, "メール確認"))
    heapq.heappush(tasks, (1, "緊急会議"))
    heapq.heappush(tasks, (3, "報告書作成"))
    
    # 優先度順にタスクを実行
    while tasks:
        priority, task = heapq.heappop(tasks)
        print(f"実行するタスク: {task} (優先度: {priority})")

# タスクスケジューラの実行
task_scheduler()
```

出力
```plaintext
実行するタスク: 緊急会議 (優先度: 1)
実行するタスク: メール確認 (優先度: 2)
実行するタスク: 報告書作成 (優先度: 3)
```
<br><br>
- ### 3-7 `bisect` --- 配列二分法アルゴリズム
 `bisect` モジュールは、ソートされたリストに対して高速な検索や挿入を行うための関数を提供します。二分探索を使用して挿入位置を効率的に決定し、リストをソートされた状態に保ちながら要素を追加できます。
 
 `bisect_left()` と `bisect_right()` で挿入位置を探し、`insort_left()` と `insort_right()` で実際に挿入を行います。これにより、ソートされたリストを効率的に操作することができます。

 #### 主な機能

- **`bisect.bisect_left(list, value, lo=0, hi=len(list))`**:挿入位置を左から探索
この関数は、ソートされたリスト `list` に対して、`value` を挿入するための位置を探します。lo と hi の範囲内で、`value` より大きい最初の要素の位置を返します。もし `value` がリスト内にすでに存在している場合、その位置の最初の位置を返します（挿入位置としては左側）。


- **`bisect.bisect_right(list, value, lo=0, hi=len(list))`**:挿入位置を右から探索

- **`bisect.bisect_left(list, value, lo=0, hi=len(list))`**:左側から挿入


- **`bisect.insort_right(list, value, lo=0, hi=len(list))`**:右側から挿入


#### 利用例
```python
import bisect

# 初期のソートされたリスト
lst = [1, 2, 4, 5]

# 3を挿入すべき位置を探す
position = bisect.bisect_left(lst, 3)
print(f"3を挿入すべき位置: {position}")  # 出力: 2

# 3をリストに挿入（ソート順を保つ）
bisect.insort_left(lst, 3)
print(f"3を挿入後のリスト: {lst}")  # 出力: [1, 2, 3, 4, 5]
```

<br><br>
- ### 3-8 `array` --- 効率的な数値配列
`array` モジュールは、効率的な配列操作を提供するモジュールです。このモジュールは、数値データを格納するために設計されており、通常のリストよりもメモリ効率が良く、特定のデータ型に制限をかけることができます。

#### 主な機能
- **`array()`**：数値データ型の配列を作成するためのクラス。リストに似ていますが、より効率的にメモリを使用できます。

- **`型コード`**:配列を作成する際に、格納するデータ型を指定するためのコード。例えば、`'i'` は整数、`'f'` は浮動小数点数を示します。

#### 利用例
 `array`モジュールを使えば、特定のデータ型の配列を効率的に扱うことができ、特に数値データを大量に扱う場合に便利です。
 ```python
 import array

# 整数型の配列を作成
arr = array.array('i', [10, 20, 30, 40, 50])

# 配列の要素を出力
print(arr)
# 配列全体を表示: array('i', [10, 20, 30, 40, 50])

# 配列の要素にアクセス
print(arr[2])  
# 30が表示される（インデックス2の要素を表示）

# 配列に新しい要素を追加
arr.append(60)
print(arr)
# array('i', [10, 20, 30, 40, 50, 60])（60が追加される）
```
:::note warn
 `array`モジュールは、通常のリストよりもメモリ効率が良いため、大量の数値データを扱う際に適していますが、リストのように汎用的なデータ型を扱うことはできません。
:::

<br><br>
 - ### 3-9 `weakref` --- 弱参照
`weakref` モジュールは、オブジェクトへの「弱い参照（weak reference）」を提供するための機能を提供します。通常の参照は強い参照（strong reference）と呼ばれ、参照されているオブジェクトが解放されることなく、オブジェクトがメモリから消えることはありません。一方、弱い参照は、オブジェクトのメモリ解放を妨げず、オブジェクトのガーベジコレクション（GC）を可能にします。

:::note info
`weakref` モジュールは、特にキャッシュや循環参照の回避に役立ちます。弱い参照を使用すると、オブジェクトが他のオブジェクトから参照されていなくても、メモリを効率的に管理できるようになります。
:::

#### 主な機能
- **`weakref.ref(object, callback=None)`**:弱い参照を作成するための関数。弱い参照は、オブジェクトを参照しますが、そのオブジェクトを解放することを妨げません。

- **`weakref.proxy(object)`**:弱い参照のプロキシオブジェクトを作成します。プロキシオブジェクトは、参照元オブジェクトと同じように振る舞いますが、元のオブジェクトが解放されると、自動的に None を返します。

- **`weakref.finalize(object, func, *args, **kwds)`**:オブジェクトがガーベジコレクションによって解放される際に呼び出すコールバック関数を設定できます。


#### 利用例
`weakref.ref`や`weakref.proxy`を使うことで、オブジェクトの解放を待機しながら、リソースの効率的な管理や循環参照の回避が可能になります。

```python
import weakref

class MyClass:
    def __del__(self):
        print("MyClass instance is being destroyed")

# オブジェクトを作成
obj = MyClass()

# 弱い参照を作成
weak_obj = weakref.ref(obj)

# 弱い参照を使ってオブジェクトにアクセス
print(weak_obj())  # オブジェクトが存在する場合、そのオブジェクトが表示される

# オブジェクトを削除
del obj

# 弱い参照が無効になるとNoneが返る
print(weak_obj())  # Noneが表示される（オブジェクトはガーベジコレクションされたため）
```

<br><br>
 - ### 3-10 `types` --- 動的な型生成と組み込み型の名前
`types` モジュールは、Pythonのさまざまなオブジェクトの型を識別するための定数や関数を提供します。このモジュールには、ビルトイン型のクラスやオブジェクトタイプを識別するためのツールが含まれており、動的な型チェックや型に基づいた操作を効率的に行うことができます。

#### 主な機能
- **`FunctionType(code, globals=None, name="<function>", argdefs=None, closure=None)`**: Python の関数型を示す型オブジェクト。

- **`MethodType(function, instance, class=None)`**: メソッド型を示す型オブジェクト。通常、クラスのインスタンスメソッドを指します。

- **`LambdaType`**: lambda 式によって作られた関数型を示す型オブジェクト。

- **`BuiltinFunctionType`**: ビルトイン関数の型オブジェクト。例えば、len() や print() などの組み込み関数。

#### 利用例
```python
import types

# 関数の定義
def my_function():
    pass

# 関数の型チェック
if isinstance(my_function, types.FunctionType):
    print("my_function is a function")
else:
    print("my_function is not a function")

# ビルトイン関数の型チェック
if isinstance(len, types.BuiltinFunctionType):
    print("len is a built-in function")
```

<br><br>
- ### 3-11 `copy` --- 浅いコピーおよび深いコピー
`copy` モジュールは、オブジェクトの複製を行うための機能を提供します。このモジュールを使うことで、オブジェクトを簡単にコピーすることができ、特にミュータブル（可変）オブジェクトを扱う際に有用です。copy モジュールには、シャローコピー（浅いコピー）とディープコピー（深いコピー）を作成するための関数が用意されています。

#### 主な機能
:::note info
`copy()`: シャローコピーを作成します。オブジェクト自体は新しく作成されますが、内部のオブジェクトは元のオブジェクトの参照を保持します。つまり、内部のオブジェクトが変更されると、元のオブジェクトにも影響があります。

`depcopy()`:ディープコピーを作成します。オブジェクト自体と内部のオブジェクトすべてが新しくコピーされ、元のオブジェクトとは完全に独立した新しいオブジェクトが作成されます。
:::

```python
import copy

# シャローコピーの例
original_list = [1, 2, [3, 4]]
shallow_copy = copy.copy(original_list)

# シャローコピーの変更
shallow_copy[2][0] = 99

print("Original list:", original_list)  # 内部のリストが変更されている
print("Shallow copy:", shallow_copy)

# ディープコピーの例
deep_copy = copy.deepcopy(original_list)

# ディープコピーの変更
deep_copy[2][0] = 42

print("Original list:", original_list)  # 元のリストは変更されていない
# 出力:Original list: [1, 2, [99, 4]]
print("Deep copy:", deep_copy)
# 出力:Deep copy: [1, 2, [42, 4]]
```

<br><br>
- ### 3-12 `pprint` --- データの整形表示
`pprint` モジュールは、データ構造を見やすく整形して表示するための機能を提供します。特に、辞書やリストのようなネストされたデータを、より読みやすく出力するために役立ちます。pprint を使うことで、標準の `print` 関数では見づらい複雑なデータを、きれいに整形して表示することができます。

#### 主な機能

- **`pprint()`**:データ構造を整形して表示する関数。辞書やリスト、タプルなどのネストされた構造をきれいに表示します。

- **`PrettyPrint()`**: より高度なカスタマイズを行いたい場合に使用できるクラス。出力の幅やインデントなどの設定を変更することができます。

#### 利用例

```python
import pprint

# 複雑なネストされたデータ構造
data = {
    'name': 'Alice',
    'age': 30,
    'address': {
        'street': '123 Main St',
        'city': 'Wonderland',
        'zipcode': '12345'
    },
    'phones': ['123-4567', '890-1234']
}

# pprintを使って見やすく表示
pprint.pprint(data)
```
 出力例
```python
{'address': {'city': 'Wonderland', 'street': '123 Main St', 'zipcode': '12345'},
 'age': 30,
 'name': 'Alice',
 'phones': ['123-4567', '890-1234']}
 ```





<br><br>
- ### 3-13 `reprlib` --- カスタマイズ可能な `repr()`
`reprlib` モジュールは、オブジェクトの `repr()` 表現をカスタマイズするためのツールを提供します。

:::note info
特に、大きなデータ構造や複雑なオブジェクトを出力する際に、出力を制限したり、トリミングしたりして、より読みやすくするために利用されます。デフォルトでは、Python の repr() 関数はオブジェクトの詳細な文字列表現を返しますが、`reprlib` を使うと、この表現を制御することができます。 
:::

#### 主な機能
- **`reprlib.repr(object)`**: `repr()` のカスタマイズ版で、長大なオブジェクトの表示を制限します。特にリストや辞書などの大きなデータ構造をコンパクトに表示するために使用されます。

- **`reprlib.aREpr()`**:`reprlib.repr()` の動作をカスタマイズしたい場合に使用できるクラス。出力の制限方法や形式を細かく設定できます。

#### 利用例
`reprlib.repr()`を使うと、大きなリストや辞書、またはその他のデータ構造の出力を制限し、簡潔に表示することができます。

```python
import reprlib

# 大きなリスト
long_list = [i for i in range(100)]

# reprlib.reprを使って簡潔に表示
print(reprlib.repr(long_list))
# 出力:[0, 1, 2, 3, 4, 5, ...]
# reprで出力すると、省略されずに0~99まで全て表示される。
```
`reprlib.repr()` を使うことで、非常に大きなデータ構造をコンパクトに表示でき、デバッグやログ出力時に非常に便利です。

#### `reprlib.Repr`クラスの使用例
`reprlib.Repr`クラスを使うと、`repr() `の動作をより細かくカスタマイズできます。例えば、どれだけ表示を制限するか、またどのように省略表現を使うかを指定できます。

```python
import reprlib

class MyRepr(reprlib.Repr):
    def __init__(self):
        super().__init__()
        self.maxlist = 10  # リストの最大表示要素数を10に設定
    
    def repr_list(self, obj, level):
        # リストの要素を制限して表示するカスタム実装
        if len(obj) > self.maxlist:
            return '[' + ', '.join(self.repr1(x, level-1) for x in obj[:self.maxlist-1]) + ',,, etc ]'
        return '[' + ', '.join(self.repr1(x, level-1) for x in obj) + ']'

large_list = [i for i in range(100)]
my_repr = MyRepr()
print(my_repr.repr(large_list)) 
#出力:[0, 1, 2, 3, 4, 5, 6, 7, 8,,, etc ]
```
　　　　　　
<br><br>
 - ### 3-14 `enum` --- 列挙型サポート
`enum` モジュールは、列挙型（Enum）をサポートするためのモジュールです。列挙型は、固定された定数の集合を定義し、それに名前を付けることができるデータ型です。

定数値を管理する際に、誤った値を防ぎ、名前付きで意味を明確にするために使われます。

状態遷移やフラグの管理などで、数値や文字列の代わりに明確な名前を使いたい場合に便利です。

#### 主な機能
- **`enum`**: 基本的な列挙型クラス。ユーザー定義の列挙型を作成するために使用します。
　　　　
- **`IntEnum`**:整数型の列挙型。列挙値が整数として扱われることを保証します。
　　　　　
- **`Flag`**:複数のフラグ（ビット単位の値）を組み合わせることができる列挙型。
　　　　　
- **`auto()`**:列挙型の値を自動で割り当てるための関数。

#### 利用例
```python
from enum import Enum, auto

class AutoColor(Enum):
    RED = 1
    BLUE = 2
    GREEN = 3

print(AutoColor.RED.value) # 1
print(AutoColor.GREEN.value)  # 3

print(AutoColor.RED.name) # RED
print(AutoColor.GREEN.name)  # GREEN
```


```python
# フラグの使用例
from enum import Flag, auto

class Permissions(Flag):
    READ = auto()
    WRITE = auto()
    EXECUTE = auto()

# 複数のフラグを組み合わせる
user_permissions = Permissions.READ | Permissions.WRITE

# フラグの確認
print(user_permissions)             # Permissions.READ|WRITE
print(Permissions.READ in user_permissions)  # True
```

:::note info
`Flag` と `IntEnum` は、特殊な用途に合わせて拡張された列挙型で、ビット操作を利用したフラグや整数値の列挙型に使います。

`Enum` メンバーは、変更不可能（イミュータブル）であるため、後から値を変更することはできません。
:::

<br><br>
 - ### 3-15 `graphlib` --- グラフ構造を操作する機能
`graphlib` モジュールは、グラフ構造（特に有向グラフ）を操作するための機能を提供します。主に、トポロジカルソート（依存関係に基づく順序付け）を行うために使用されます。
#### 主な機能

- **`TopologicalSorter(graph)`**:複数のタスクがあって、タスク同士に依存関係（順番）があるときに、その依存関係を解決して順番を決めるためのものです。


- **`static_order()`**:依存関係を解決した「実行順番」をリストとして返します。

#### 利用例
```python
from graphlib import TopologicalSorter

# タスクとその依存関係を定義
tasks = {
    'task1': [],           # task1 は依存するタスクなし
    'task2': ['task1'],    # task2 は task1 に依存
    'task3': ['task1'],    # task3 は task1 に依存
    'task4': ['task2', 'task3'],  # task4 は task2 と task3 に依存
}

# トポロジカル順序でタスクをソート
sorter = TopologicalSorter(tasks)
order = list(sorter.static_order())  # 順番をリストで取得

print(order)  # ['task1', 'task2', 'task3', 'task4']
```
この例では、task1 が最初に実行され、次に task2 と task3 が実行され、最後に task4 が実行される順番になります。`static_order()` は、その順番をリストで返してくれます。


## 4. 数値と数学モジュール
- ### 4-1 `numbers` --- 数の抽象基底クラス
`numbers` モジュールは、数値型を扱うための抽象基底クラスを提供します。このモジュールは、数値型の階層構造を定義し、異なる種類の数値（整数、浮動小数点数、複素数など）を扱う際に便利です。特に、カスタム数値型を作成する際や、異なる数値型を柔軟に扱うために使用されます。

#### 主な機能
- **`Number`**: すべての数値型の基底クラス。
- **`Complex`**: 複素数型の基底クラス。
- **`Real`**: 実数型の基底クラス。
- **`Integral`**: 整数型の基底クラス。
- **`Rational`**: 有理数型の基底クラス。
- **`Float`**: 浮動小数点型の基底クラス。

#### 利用例
```python
import numbers

# 数値かどうかをチェック
x = 10
if isinstance(x, numbers.Integral):
    print(f"{x} は整数です")

y = 3.14
if isinstance(y, numbers.Real):
    print(f"{y} は実数です")
```

 出力
```
10 は整数です
3.14 は実数です
```


<br><br>
 - ### 4-2 `math` --- 数学関数
`math` モジュールは、数学的な計算を行うための多くの関数と定数を提供します。このモジュールを使用することで、三角関数、対数、指数、平方根など、さまざまな数学的処理を簡単に行うことができます。

#### 主な機能
- **`sin(x), cos(x), tan(x)`**: 三角関数（弧度法で計算）。
- **`sqrt(x)`**: 平方根を計算。
- **`log(x, base)`**: 対数（任意の基数で計算）。
- **`exp(x)`**: 指数関数。
- **`pi`**: 円周率（π）。
- **`e`**: ネイピア数（e）。
- **`fabs(x)`**: 絶対値を計算。
#### 利用例
math モジュールを使用して、一般的な数学的操作を簡単に実行できます。

```python

import math

# 三角関数の例
angle = math.pi / 4  # 45度（弧度法）
print(math.sin(angle))  # sin(45°) の結果
#0.7071067811865475  # sin(45°)
# 指数と対数の例
print(math.exp(1))  # e の1乗（ネイピア数）
#2.718281828459045
print(math.log(100, 10))  # 100 の底 10 の対数
#2.0  # log(100) base 10

# 平方根の例
print(math.sqrt(16))  # 16 の平方根
#4.0  # sqrt(16)


# 絶対値の例
print(math.fabs(-5))  # -5 の絶対値
#5.0  # fabs(-5)

```


<br><br>
- ### 4-3 `cmath` --- 複素数用の数学関数
`cmath` モジュールは、複素数に関連する数学的な操作を行うための関数を提供します。通常の実数の計算とは異なり、複素数に対しても対応できる関数群を提供しており、複素数の絶対値、偏角、平方根、対数、指数関数などを計算することができます。

#### 主な機能
- **`phase(z)`**: 複素数 z の偏角（角度）を返します。
- **`polar(z)`**: 複素数 z を極座標形式 (絶対値、偏角) で返します。
- **`rect(r, phi)`**: 極座標 (r, φ) を複素数形式に変換します。
- **`sqrt(z)`**: 複素数 z の平方根を計算します。
- **`log(z)`**: 複素数 z の自然対数を計算します。
- **`exp(z)`**: 複素数 z の指数関数を計算します。

#### 利用例

```python
import cmath

# 複素数の定義
z = 3 + 4j  # 3 + 4i

# 絶対値（複素数の大きさ）を計算
print(cmath.abs(z))  # 結果: 5.0

# 偏角（複素数の角度）を計算
print(cmath.phase(z))  # 結果: 0.9272952180016122

# 極座標に変換
polar_form = cmath.polar(z)
print(polar_form)  # 結果: (5.0, 0.9272952180016122)

# 極座標から複素数に変換
rect_form = cmath.rect(5.0, 0.9272952180016122)
print(rect_form)  # 結果: (3+4j)

# 複素数の平方根
print(cmath.sqrt(z))  # 結果: (2.0+1j)

# 複素数の自然対数
print(cmath.log(z))  # 結果: (1.6094379124341003+0.9272952180016122j)
```


                     
 <br><br>                                                                                    
 - ### 4-4 `decimal` --- 10進小数点の演算
`decimal` モジュールは、10進小数点の精度を制御し、精度の高い浮動小数点演算を行うための機能を提供します。通常の浮動小数点演算では、計算誤差が発生することがありますが、`decimal` モジュールを使うと、精度を高く保ちながら計算を行うことができます。

#### 主な機能
- **`Decimal(value)`**: 
 高精度な10進数の演算を提供するクラス。小数点以下の精度を指定して計算することができます。value は任意の数値を表す文字列、整数、または浮動小数点数です。ただし、浮動小数点数を直接渡す場合、内部での精度の問題が生じる可能性があるため、str で指定する方が望ましいです。
　　　　

- **`getcontext()`**:
現在の計算精度を取得・設定する関数。getcontext() 自体には引数はなく、現在のコンテキストに関する情報（精度や丸めモードなど）を取得できます。
取得した Context オブジェクトを使って、精度や丸めモードなどの設定を変更できます。

- **`ROUND_HALF_UP`**, **`ROUND_DOWN`** など: 四捨五入の方法を指定する定数。
#### 利用例

```python
import decimal

# Decimal型の数値を使う
a = decimal.Decimal('0.1')
b = decimal.Decimal('0.2')

# 演算例: 足し算
result = a + b
print(result)  # 結果: 0.3

# 精度の設定
decimal.getcontext().prec = 6  # 計算精度を6桁に設定
c = decimal.Decimal('1') / decimal.Decimal('3')
print(c)  # 結果: 0.333333

# 四捨五入の指定
d = decimal.Decimal('2.675')
rounded = d.quantize(decimal.Decimal('0.01'), rounding=decimal.ROUND_HALF_UP)
print(rounded)  # 結果: 2.68（四捨五入）
```

<br>

- ### 4-5 `fractions` --- 有理数
`fractions` モジュールは、有理数の演算を扱うための機能を提供します。有理数同士の加算、減算、乗算、除算を正確に行うことができます。

:::note info
有理数とは、整数の比として表される数で、分子と分母の両方が整数である数です。
:::

#### 主な機能
- **`Fraction(value)`**: 有理数を表すクラス。分子と分母を指定して、有理数を作成できます。
　　　　
- **`limit_denominator(int)`**: 有理数を近似するために、指定した分母の範囲内で最も近い有理数を求めます。
　　　　
- **`numerator`**: 有理数の分子を取得します。
　　　　
- **`denominator`**: 有理数の分母を取得します。
#### 利用例
fractions モジュールを使用して、有理数の演算を行う方法を示します。

```python
from fractions import Fraction

# 有理数の作成
fraction1 = Fraction(3, 4)  # 3/4
fraction2 = Fraction(5, 6)  # 5/6

# 加算
result_add = fraction1 + fraction2
print(result_add)  # 結果: 19/12

# 減算
result_sub = fraction1 - fraction2
print(result_sub)  # 結果: -1/12

# 乗算
result_mul = fraction1 * fraction2
print(result_mul)  # 結果: 15/24 => 5/8（約分される）

# 除算
result_div = fraction1 / fraction2
print(result_div)  # 結果: 18/20 => 9/10（約分される）

# 分子と分母の取得
print(fraction1.numerator)  # 結果: 3
print(fraction1.denominator)  # 結果: 4

# 分母を制限した近似
approx_fraction = fraction1.limit_denominator(10)
print(approx_fraction)  # 結果: 3/4（近似で変化しない）
```



<br><br>

 - ### 4-6 `random` --- 疑似乱数生成
`random` モジュールは、疑似乱数の生成を行うための機能を提供します。乱数を使ったシミュレーションや、ランダムな選択、シャッフルなど、さまざまな場面で利用できます。

#### 主な機能
- **`random()`**: 0.0 以上 1.0 未満のランダムな浮動小数点数を生成。
- **`randint(a, b)`**: 指定した範囲 [a, b] からランダムな整数を生成。
- **`choice(seq)`**: シーケンスからランダムに1つの要素を選択。
- **`shuffle(lst)`**: リストの要素をランダムに並べ替え。
- **`sample(population, k)`**: シーケンスから k 個の要素をランダムに選択（重複なし）。
- **`uniform(a, b)`**: 指定した範囲 [a, b] でランダムな浮動小数点数を生成。

#### 利用例
```python
import random #(出力結果は出力の度,変化する)
import string

# 0.0以上1.0未満のランダムな浮動小数点数を生成
random_float = random.random()
print(random_float)
#出力:0.543672332

# 1から10までのランダムな整数を生成
random_int = random.randint(1, 10)
print(random_int)
#出力:4


# 文字列からランダムに1文字を選ぶ
random_char = random.choice(string.ascii_letters)
print(random_char)
#出力:S

# リストをランダムにシャッフル
lst = [1, 2, 3, 4, 5]
random.shuffle(lst)
print(lst)
#出力:[5, 3, 2, 1, 4]

# リストから2つのランダムな要素を選択（重複なし）
random_sample = random.sample(lst, 2)
print(random_sample)
#出力:[5, 2]

# 1.0以上5.0未満のランダムな浮動小数点数を生成
random_uniform = random.uniform(1.0, 5.0)
print(random_uniform)
#出力:2.936175297
```

 

<br><br>

 - ### 4-7 `statistics` --- 統計関数
statistics モジュールは、基本的な統計計算を簡単に行うための関数を提供します。データセットに対して平均値、中央値、分散、標準偏差などを求める際に非常に便利です。

#### 主な機能
- **`mean(data)`**: データの算術平均（平均値）を求めます。
- **`median(data)`**: データの中央値（中央値）を求めます。
- **`mode(data)`**: 最頻値（最も頻繁に出現する値）を求めます。
- **`variance(data)`**: データの分散を計算します。
- **`stdev(data)`:** データの標準偏差を計算します。
- **`harmonic_mean(data)`**: 調和平均を計算します。
- **`fmean(data)`**: 浮動小数点数データに対して平均を求めます。
- **`quantiles(data, n = int)`**: データの分位点を計算します。

#### 利用例

```python
import statistics

# サンプルデータ
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 算術平均（mean）
mean_value = statistics.mean(data)
print(f"Mean: {mean_value}")
#出力:Mean: 5.5

# 中央値（median）
median_value = statistics.median(data)
print(f"Median: {median_value}")
#出力:Median: 5.5

# 最頻値（mode）
# データに最頻値が複数ある場合はエラーになるので、その場合の扱いに注意
data_with_mode = [1, 2, 2, 3, 4, 5]
mode_value = statistics.mode(data_with_mode)
print(f"Mode: {mode_value}")
#出力:Mode: 2

# 分散（variance）
variance_value = statistics.variance(data)
print(f"Variance: {variance_value}")
#出力:Variance: 9.166666666666666

# 標準偏差（stdev）
stdev_value = statistics.stdev(data)
print(f"Standard Deviation: {stdev_value}")
#出力:Standard Deviation: 3.0276503540974917

# 調和平均（harmonic mean）
harmonic_mean_value = statistics.harmonic_mean(data)
print(f"Harmonic Mean: {harmonic_mean_value}")
#出力:Harmonic Mean: 3.4146341463414633

# 分位点（quantiles）
quantiles_value = statistics.quantiles(data, n=4)  # 四分位点
print(f"Quantiles: {quantiles_value}")
#出力:Quantiles: [3.0, 6.0, 9.0]
```



## 5. 関数型プログラミング用モジュール
- ### 5-1 `itertools` --- 効率的なループ用イテレータ生成
`itertools` モジュールは、効率的なイテレータの生成を行うための関数を提供します。このモジュールは、反復処理（ループ処理）を簡素化し、効率的に扱えるようにするツールが豊富です。特に、メモリ効率が良いため、大規模なデータセットを扱う際にも効果的です。

#### 利用例
- **`count(start=0, step=1)`**: 無限に続く整数のイテレータを生成します。
　　
- **`cycle(iterable)`**: シーケンスを無限に繰り返すイテレータを生成します。
　　

- **`repeat(object, times=None)`**: 同じオブジェクトを指定回数繰り返すイテレータを生成します。

- **`chain(*iterables)`**: 複数のイテラブルを連結して1つのイテレータにします。
　　　
- **`zip_longest(*iterables, fillvalue=None)`**: 複数のイテラブルを長さが一致するまで並べ、足りない部分を fillvalue で埋めます。
　　

- **`combinations(iterable, r)`**: イテラブルから r 個の要素を順不同で選ぶ組み合わせのイテレータを生成します。

#### 利用例
```python
import itertools

# count: 無限に続く整数を生成
counter = itertools.count(start=10, step=2)
for i in range(5):
    print(next(counter)) 
#10
#12
#14
#16
#18

# cycle: シーケンスを無限に繰り返す
cycler = itertools.cycle(['A', 'B', 'C'])
for _ in range(6):
    print(next(cycler))
#A
#B
#C
#A
#B
#C

# repeat: 同じオブジェクトを繰り返す
repeater = itertools.repeat('Hello', times=3)
for item in repeater:
    print(item)
#Hello
#Hello
#Hello

# chain: 複数のリストを連結する
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
combined = itertools.chain(list1, list2)
for item in combined:
    print(item)
#1
#2
#3
#a
#b
#c

# zip_longest: 長さの異なるリストを埋めて結合する
list3 = [1, 2, 3]
list4 = ['a', 'b']
zipped = itertools.zip_longest(list3, list4, fillvalue='-')
for item in zipped:
    print(item)
#(1, 'a')
#(2, 'b')
#(3, '-')


# combinations: 組み合わせを生成
combs = itertools.combinations([1, 2, 3, 4], 2)
for comb in combs:
    print(comb)
#(1, 2)
#(1, 3)
#(1, 4)
#(2, 3)
#(2, 4)
#(3, 4)


# permutations: 順列を生成
perms = itertools.permutations([1, 2, 3], 2)
for perm in perms:
    print(perm)
#(1, 2)
#(1, 3)
#(2, 1)
#(2, 3)
#(3, 1)
#(3, 2)

# product: デカルト積を生成
prod = itertools.product([1, 2], ['A', 'B'], repeat=2)
for p in prod:
    print(p)
#(1, 'A', 1, 'A')
#(1, 'A', 1, 'B')
#(1, 'A', 2, 'A')
#(1, 'A', 2, 'B')
#(1, 'B', 1, 'A')
#(1, 'B', 1, 'B')
#(1, 'B', 2, 'A')
#(1, 'B', 2, 'B')
#(2, 'A', 1, 'A')
#(2, 'A', 1, 'B')
#(2, 'A', 2, 'A')
#(2, 'A', 2, 'B')
#(2, 'B', 1, 'A')
#(2, 'B', 1, 'B')
#(2, 'B', 2, 'A')
#(2, 'B', 2, 'B')
```
 


<br><br>



- ### 5-2 `functools` --- 高階関数と呼び出し可能オブジェクト
`functools` モジュールは、関数や呼び出し可能なオブジェクトを操作するための高階関数を提供します。これにより、関数をより効率的に使うためのツールや便利な機能を活用することができます。

#### 主な機能

- **`partial(func)`**: 引数の一部をあらかじめ固定した新しい関数を生成するための関数です。これにより、関数をカスタマイズして再利用性を高めることができます。 
　　　
    
- **`lru_cache(maxsize,typed)`**: 最後に呼び出した結果をキャッシュして、再度同じ計算をする際に高速化を図るためのデコレーターです。
 　　　 
- **`reduce(function, iterable, initializer=None)`**: 反復可能なオブジェクト（リストなど）の要素を累積的に処理して単一の値にする関数です。
　　
- **`wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)`**: デコレーターを使ってラップされた関数に、元の関数のメタデータ（名前やドキュメントなど）を引き継ぐための関数です。
　　　　      
- **`total_ordering()`**: クラスに対して、比較演算子を1つまたは2つだけ定義すれば、残りの比較演算子を自動的に定義するためのクラスデコレーターです。

#### 利用例

```python
from functools import partial

def power(base, exponent):
    return base ** exponent

# 2をベースにした累乗関数を生成
square = partial(power, 2)
print(square(3))  # 出力: 8
```
lru_cache を使ったキャッシュ 計算結果をキャッシュすることで、同じ計算を繰り返さず効率的に処理を行う例です。

```python
from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100))  # 計算結果がキャッシュされるため、高速に計算される
# 出力:354224848179261915075
```
reduce を使った累積的な処理 reduce を使用してリストの要素を累積的に処理し、1つの結果を得る例です。

```python
from functools import reduce

numbers = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x + y, numbers)
print(result)  # 出力: 15
```
wraps を使ったデコレーター デコレーターで関数のメタデータを保持する方法です。

```python
from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@decorator
def say_hello(name):
    """Say hello to the user."""
    print(f"Hello, {name}!")

say_hello("Alice")
print(say_hello.__name__)  # 出力: say_hello
```

<br><br>
 
 - ### 5-3 `operator` --- 関数形式の標準演算子
 `operator` モジュールは、演算子を関数形式で提供し、関数型プログラミングをサポートします。以下は簡潔な利用例です。

#### 主な関数と利用例

```python

import operator

# 加算
print(operator.add(2, 3))  # 出力: 5

# 乗算
print(operator.mul(4, 5))  # 出力: 20

#比較演算
print(operator.eq(3, 3))  # 出力: True
print(operator.lt(2, 5))  # 出力: True


#論理演算
print(operator.and_(True, False))  # 出力: False
print(operator.or_(True, False))   # 出力: True



#ビット演算
print(operator.and_(5, 3))  # 出力: 1 (5 & 3)
print(operator.or_(5, 3))   # 出力: 7 (5 | 3)



#リスト操作
lst = [10, 20, 30, 40]
print(operator.getitem(lst, 2))  # 出力: 30

operator.setitem(lst, 1, 25)
print(lst)  # 出力: [10, 25, 30, 40]


#map() との組み合わせ
numbers = [1, 2, 3, 4]
print(list(map(operator.add, numbers, [10, 10, 10, 10])))  # 出力: [11, 12, 13, 
```

## 6. ファイルとディレクトリへのアクセス
 - ### 6-1 `pathlib` --- オブジェクト指向のファイルパス操作
 `pathlib` モジュールは、ファイルパスをオブジェクト指向で操作できます。従来の文字列操作ではなく、パス操作をオブジェクトとして扱うことで、コードを直感的で読みやすくします。

#### 主な機能
- **`pathlib.Path()`**: path 引数で指定されたパスを持つ Path オブジェクトを作成します
- **`Path.cwd()`**:現在の作業ディレクトリ（カレントディレクトリ）を返します。
- **`Path.home()`**:ユーザーのホームディレクトリを返します。
- **`Path.glob(pattern)`**:パターン（ワイルドカード）に一致するファイルを返すジェネレータです。カレントディレクトリや指定したディレクトリでファイル名をパターンマッチングします。

    

#### 利用例

```python
from pathlib import Path

path = Path("my_folder") / "subfolder" / "file.txt"
print(path)  # 出力: my_folder/subfolder/file.txt
```
ファイルやディレクトリの存在確認


```python
path = Path("example.txt")

if path.exists():
    print("ファイルが存在します")
else:
    print("ファイルが存在しません")
```
ディレクトリの作成 mkdir() を使ってディレクトリを作成できます。

```python
path = Path("new_directory")
path.mkdir(exist_ok=True)  # すでに存在してもエラーを出さない
```

```python
path = Path("sample.txt")

# ファイルの書き込み
path.write_text("Hello, World!")

# ファイルの読み込み
content = path.read_text()
print(content)  # 出力: Hello, World!
```

パスの親ディレクトリや拡張子の取得
```python
path = Path("my_folder/subfolder/file.txt")

# 親ディレクトリ
print(path.parent)  # 出力: my_folder/subfolder

# 拡張子
print(path.suffix)  # 出力: .txt
```

<br><br>

 - ### 6-2 `os.path` --- パス名操作
 `os.path` モジュールは、ファイルパスの操作を行うための関数を提供します。パスの結合や分割、正規化、存在確認など、ファイルシステムとのインタラクションを簡潔に行うために使用されます。特に、クロスプラットフォームで動作するコードを書く際に非常に便利です。

#### 主な機能
- **`os.path.join(path, *paths)`**: OSに依存しない方法でパスを結合できます。
- **`os.path.split(path), os.path.splitext()`**: ファイルパスを分割できます。
- **`os.path.exists(path)`**: ファイルやディレクトリの存在を確認できます。
- **`os.path.normpath(path)`**: パスを正規化できます。
- **`os.path.splitext(path)`**: ファイルの拡張子を取得できます。
#### 利用例
1.パスの結合 os.path.join() を使用して、複数のパスを結合します。
```python
import os

path = os.path.join("my_folder", "subfolder", "file.txt")
print(path)  # 出力: my_folder/subfolder/file.txt
```
パスの分割 os.path.split() でディレクトリパスとファイル名に分割できます。

```python
import os

path = "my_folder/subfolder/file.txt"
dir_name, file_name = os.path.split(path)
print(dir_name)  # 出力: my_folder/subfolder
print(file_name)  # 出力: file.txt
```
2.拡張子の取得 os.path.splitext() でファイルの拡張子を取得できます。

```python
import os

path = "my_folder/subfolder/file.txt"
root, ext = os.path.splitext(path)
print(root)  # 出力: my_folder/subfolder/file
print(ext)   # 出力: .txt
```
3.パスの正規化 os.path.normpath() でパスを正規化します。これにより、余分な区切り文字が削除されます。

```python
import os

path = "my_folder//subfolder/../file.txt"
normalized_path = os.path.normpath(path)
print(normalized_path)  # 出力: my_folder/file.txt
```
4.存在確認 os.path.exists() で指定したパスが存在するか確認します。

```python
import os

path = "my_folder/subfolder/file.txt"
if os.path.exists(path):
    print("ファイルが存在します")
else:
    print("ファイルが存在しません")
```
5.ディレクトリの作成 os.path.isdir() や os.makedirs() を使って、ディレクトリを作成できます。

```python
import os

path = "my_folder/subfolder"
if not os.path.exists(path):
    os.makedirs(path)  # サブディレクトリも含めて作成
```
- ### 6-3 `fileinput` --- 複数入力ストリームの行反復
`fileinput` モジュールは、複数の入力ストリーム（ファイルや標準入力など）から行単位でデータを反復処理するための便利なツールを提供します。このモジュールは、特に複数のファイルを順番に処理したり、標準入力からのデータを処理する際に便利です。

#### 主な機能
- **`fileinput("file","*file")`**: 複数のファイルを順番に処理することができます。

 - **`fileinput.filename()`**:現在処理中のファイル名を文字列として返します。複数のファイルを順番に処理している場合、fileinput.filename() はその時点で処理中のファイルの名前を返します。
　　　　　　　
#### 利用例
1.ファイルからの行読み込み 複数のファイルを順に読み込み、各行を処理する例です。

```python
import fileinput

# 複数のファイルを指定して行を読み込む
for line in fileinput.input(files=["file1.txt", "file2.txt"]):
    print(line.strip())  # 各行を出力
```
2.標準入力からの行読み込み 標準入力をファイルとして処理し、行ごとに読み込む例です。

```python
import fileinput

# 標準入力を処理
for line in fileinput.input():
    print(line.strip())
# 行の前後の空白を削除して出力
```
この例では、コマンドラインで実行する際に標準入力から入力を受け取り、行ごとに処理します。例えば、次のように使用できます：

```css
python script.py < input.txt
```
3.行の修正と書き込み fileinput はファイルを編集するためにも使用できます。特に、ファイル内の行を変更する際に便利です。ファイルをインプレースで変更することができます。

```python
import fileinput

# 'file1.txt' をインプレースで変更
for line in fileinput.input(files="file1.txt", inplace=True):
    # 行が "old" を含んでいれば "new" に置き換える
    print(line.replace("old", "new"), end="")
# 行が "old" を含んでいれば "new" に置き換えて出力
```
inplace=True により、元のファイルが直接編集されます。行ごとに変更した結果がファイルに書き込まれます。

4.ファイル名の取得 現在処理しているファイル名を取得することができます。
file1.txt の内容:
```csharp
  Hello from file 1  
  Line 2 in file 1  
```
file2.txt の内容:
```csharp
  Hello from file 2  
  Line 2 in file 2 
```

```python
import fileinput

for line in fileinput.input():
    print(f"Processing {fileinput.filename()}: {line.strip()}")
```

実行結果
```yaml
Processing file1.txt: Hello from file 1
Processing file1.txt: Line 2 in file 1
Processing file2.txt: Hello from file 2
Processing file2.txt: Line 2 in file 2
```
fileinput.filename() を使うことで、現在処理しているファイルの名前を取得できます。

5.コマンドライン引数を使ってファイルを指定 fileinput.input() は、コマンドライン引数でファイルを指定することができます。ファイルが指定されない場合、標準入力から読み込むことになります。

```python
import fileinput
import sys

# コマンドライン引数でファイルを指定
for line in fileinput.input(files=sys.argv[1:]):
    print(line.strip())
```
実行結果:
```csharp
Hello from file 1
Line 2 in file 1
Hello from file 2
Line 2 in file 2
```
この例では、コマンドライン引数で指定したファイルを順に読み込みます。
<br><br>
- ### 6-4 `stat` --- `stat()` の結果を解釈
`stat`モジュールは、ファイルやディレクトリのステータス情報を取得し、その結果を解釈するためのツールを提供します。主に `os.stat()` や `os.lstat()` の結果を解釈するために使われ、これらの関数はファイルのメタ情報（アクセス権、サイズ、最終更新日時など）を返します。

#### 主な機能
- **`os.stat(path)`**: ファイルまたはディレクトリの状態を取得します（シンボリックリンクを解決します）。
　　　　
- **`os.lstat(path)`**: シンボリックリンク自体の状態を取得します（リンク先ではなくリンクそのもの）。
　　　　
- **`stat(path) の結果を解釈`**: ファイルのタイプ、アクセス権、タイムスタンプ、サイズなどの詳細情報を取得できます。


 主な属性
- **`st_mode`**: ファイルタイプやアクセス権を示すビットフィールド。
- **`st_ino`**: inode 番号（ファイルシステム内の一意な識別子）。
- **`st_dev`**: デバイス番号（ファイルがどのデバイスにあるか）。
- **`st_nlink`**: ハードリンクの数。
- **`st_uid`**: 所有者のユーザーID（UID）。
- **`st_gid`**: 所有者のグループID（GID）。
- **`st_size`**: ファイルのサイズ（バイト単位）。
- **`st_atime`**: 最後にアクセスされた時間（Unix 時間形式）。
- **`st_mtime`**: 最後に変更された時間（Unix 時間形式）。
- **`st_ctime`**: メタデータが変更された時間（Unix 時間形式）。
これらの属性を使って、ファイルに関する詳細な情報を取得できます。

#### 利用例
1.ファイルのステータス情報の取得 `os.stat()` を使ってファイルの情報を取得し、その結果を解釈します。

```python
import os

# ファイルのステータスを取得
file_info = os.stat('example.txt')

# ファイルのサイズ
print(f"File size: {file_info.st_size} bytes")
#ex) File size: 1024 bytes

# 最後に変更された時間（Unix 時間）
print(f"Last modified: {file_info.st_mtime}")
#ex) Last modified: 1635532147.0

# 所有者のユーザーID
print(f"User ID: {file_info.st_uid}")
#ex) User ID: 1000

# グループID
print(f"Group ID: {file_info.st_gid}")
#ex) Group ID: 1000
```
2.ファイルタイプの解釈 `st_mode` 属性は、ファイルの種類やアクセス権を示すビットフィールドです。これを解釈するために `stat` モジュール内の定数を使用できます。

```python
import os
import stat

file_info = os.stat('example.txt')

# ファイルがディレクトリかどうか
if stat.S_ISDIR(file_info.st_mode):
    print("It's a directory.")
#ディレクトリの場合:It's a directory.

# ファイルが通常のファイルかどうか
elif stat.S_ISREG(file_info.st_mode):
    print("It's a regular file.")
#通常ファイルの場合:It's a regular file.
```
3.ファイルのアクセス権の取得 st_mode 属性を使って、ファイルのアクセス権を調べることができます。

```python

import os
import stat

file_info = os.stat('example.txt')

# 読み取り権限
if file_info.st_mode & stat.S_IRUSR:
    print("User has read permission")
    #User has read permission

# 書き込み権限
if file_info.st_mode & stat.S_IWUSR:
    print("User has write permission")
    #User has write permission
    
# 実行権限
if file_info.st_mode & stat.S_IXUSR:
    print("User has execute permission")
    # User has execute permission
```
4.最終アクセス時間の表示 st_atime を使って、ファイルの最終アクセス時刻を表示できます（Unix 時間を datetime 型に変換して表示）。

```python
import os
import time

file_info = os.stat('example.txt')

# 最後にアクセスされた時間（Unix 時間を変換）
last_accessed = time.ctime(file_info.st_atime)
print(f"Last accessed: {last_accessed}")
# 出力:Last accessed: Fri Oct 29 12:34:07 2024
```
<br><br>
 - ### 6-5 `filecmp` --- ファイルとディレクトリの比較
 `filecmp` モジュールは、ファイルやディレクトリを比較するためのツールを提供します。このモジュールは、2つのファイルが同一かどうか、または2つのディレクトリの内容が同じかどうかを比較するために使用できます。特に、ファイルやディレクトリの内容を効率的に比較したいときに便利です。

#### 主な機能
- **`filecmp.cmp(file1, file2, shallow=True)`**: 2つのファイルが同じかどうかを比較します。
　　　　
- **`filecmp.dircmp(dir1, dir2, ignore=None, hide=None)`**: 2つのディレクトリを比較し、その違いを調べます。
　　　　　
- **`filecmp.cmpfiles(dir1, dir2, common, shallow=True)`**: 2つのディレクトリ内のファイルを比較します。


#### 利用例
1.ファイルの比較 (filecmp.cmp())

`filecmp.cmp()` は、2つのファイルを比較して、内容が同じかどうかを確認します。デフォルトでは、ファイルの内容が同じであれば True を返し、異なる場合は False を返します。

```python
import filecmp

# 2つのファイルを比較
result = filecmp.cmp('file1.txt', 'file2.txt')
print(result)  # True ならファイルが同じ、False なら異なる
```
#### オプション

`shallow` 引数を指定することで、ファイルのメタデータ（サイズやタイムスタンプ）も考慮するか、内容のみを比較するかを制御できます。
```python
result = filecmp.cmp('file1.txt', 'file2.txt', shallow=False)  # 内容を完全に比較
```
2.ディレクトリの比較 (`filecmp.dircmp()`)

`filecmp.dircmp()` を使用すると、2つのディレクトリを比較し、ディレクトリ内のファイルやサブディレクトリの違いを詳細に確認できます。

```python
import filecmp

# 2つのディレクトリを比較
dir_cmp = filecmp.dircmp('dir1', 'dir2')

# 比較結果を出力
print(f"Common files: {dir_cmp.common_files}")  # 共通のファイル
print(f"Different files: {dir_cmp.diff_files}")  # 異なるファイル
print(f"Left only files: {dir_cmp.left_only}")  # 左のディレクトリにだけあるファイル
print(f"Right only files: {dir_cmp.right_only}")  # 右のディレクトリにだけあるファイル
```
`dircmp` オブジェクトには、以下のような属性があります：

- **`common_files`**: 両方のディレクトリに共通するファイル。
- **`diff_files`**: 異なるファイル。
- **`left_only`**: 左のディレクトリ（dir1）にだけ存在するファイル。
- **`right_only`**: 右のディレクトリ（dir2）にだけ存在するファイル。
- **`common_dirs`**: 両方のディレクトリに共通するサブディレクトリ。
- **`left_list`**: 左のディレクトリに存在するファイルとサブディレクトリ。
- **`right_list`**: 右のディレクトリに存在するファイルとサブディレクトリ。


3.ディレクトリ内のファイルの比較 (`filecmp.cmpfiles()`)

`filecmp.cmpfiles()` は、2つのディレクトリ内のファイルを比較し、内容が同じかどうかをチェックします。返される結果は、異なるファイル、同じファイル、エラーの3つのリストです。

```python
import filecmp

# 2つのディレクトリ内のファイルを比較
dir1 = 'dir1'
dir2 = 'dir2'
result = filecmp.cmpfiles(dir1, dir2, ['file1.txt', 'file2.txt'])

# 結果: (一致するファイル, 異なるファイル, エラー)
print(f"Identical files: {result[0]}")
print(f"Differing files: {result[1]}")
print(f"Errors: {result[2]}")
```
 
 :::note info
`filecmp.cmp()` はファイルの内容をバイト単位で比較しますが、shallow=False オプションを使うと、内容だけでなくファイルのメタデータ（タイムスタンプなど）も比較対象にできます。
　　　　　　
`filecmp.dircmp()` はディレクトリ単位で詳細な比較結果を返すので、ディレクトリ内のファイルやサブディレクトリの差異を容易に確認できます。
:::

<br><br>
- ### 6-6 `tempfile` --- 一時ファイルとディレクトリの作成
`tempfile` モジュールは、一時ファイルや一時ディレクトリを作成するための便利なツールを提供します。一時ファイルやディレクトリは、プログラムが一時的にデータを保存するために使用され、プログラム終了後には自動的に削除されることが多いため、安全で効率的に一時的な作業を行いたい場合に非常に便利です。

#### 主な機能
- **`TemporaryFile()`**: 一時的なファイルを作成します。ファイルが閉じられると、自動的に削除されます。
　　　　
- **`NamedTemporaryFile()`**: 名前付きの一時ファイルを作成します。ファイル名を取得でき、プログラムが終了した際に自動的に削除されます。
　　　　
- **`TemporaryDirectory()`**: 一時的なディレクトリを作成します。ディレクトリもプログラム終了時に自動的に削除されます。
　　　　　
- **`mkstemp()`**: 一時的なファイルのパスを返しますが、ファイルは自動的に削除されません。手動で削除する必要があります。
　　　　　
- **`mkdtemp()`**: 一時的なディレクトリのパスを返しますが、ディレクトリは自動的に削除されません。手動で削除する必要があります。

#### 利用例
`TemporaryFile()` を使うと、一時的なファイルを作成できます。このファイルは、ファイルオブジェクトが閉じられると自動的に削除されます。

```python
import tempfile

# 一時ファイルを作成
with tempfile.TemporaryFile(mode='w+t') as temp_file:
    temp_file.write("This is a temporary file.")
    temp_file.seek(0)  # ファイルの先頭に戻る
    print(temp_file.read())  # ファイルの内容を読み込む
# ここで temp_file は自動的に削除される
```
`mode='w+t'` はテキストモードで書き込みと読み込みを行う指定です。
with ステートメントを使うことで、temp_file が閉じられた後に自動的に削除されます。
名前付き一時ファイルの作成 (NamedTemporaryFile)

`NamedTemporaryFile()`を使うと、名前付きの一時ファイルを作成することができます。これにより、ファイル名を他のプロセスと共有することができます。ファイルが閉じられると自動的に削除されます。

```python
import tempfile

# 名前付き一時ファイルを作成
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
    print(f"Temporary file name: {temp_file.name}")
    temp_file.write(b"This is a named temporary file.")
# `delete=False` を指定すると、ファイルは閉じても削除されません
```
delete=False を指定することで、ファイルが閉じられた後も削除されないようにすることができます。
temp_file.name でファイル名にアクセスできます。


3.一時ディレクトリの作成 (`TemporaryDirectory`)

`TemporaryDirectory()` は、一時的なディレクトリを作成します。このディレクトリは、with ステートメントを使うことで自動的に削除されます。

```python
import tempfile

# 一時ディレクトリを作成
with tempfile.TemporaryDirectory() as temp_dir:
    print(f"Temporary directory created at {temp_dir}")
    # ここで temp_dir 内にファイルを作成したり操作したりできる
    # ここで temp_dir は自動的に削除される
```

with ステートメントを使うと、ディレクトリが自動的に削除されます。


一時ファイルのパスを取得

`mkstemp()` は、一時的なファイルを作成し、そのファイルのパスとファイルディスクリプタを返します。このファイルは自動的に削除されないため、手動で削除する必要があります。

```python
import tempfile

# 一時ファイルを作成し、ファイルのパスを取得
fd, path = tempfile.mkstemp()
print(f"Temporary file created at {path}")

# ファイルを開いて操作
with open(path, 'w') as temp_file:
    temp_file.write("Temporary file content.")

# 操作後に手動で削除
import os
os.remove(path)
```
fd はファイルディスクリプタ、path はファイルのパスです。ファイルは自動的に削除されないため、手動で削除する必要があります。
　　　　　
一時ディレクトリのパスを取得
`mkdtemp()` は、一時的なディレクトリを作成し、そのディレクトリのパスを返します。このディレクトリは自動的に削除されません。

```python
import tempfile

# 一時ディレクトリを作成し、そのパスを取得
temp_dir = tempfile.mkdtemp()
print(f"Temporary directory created at {temp_dir}")

# ディレクトリを操作
import os
os.rmdir(temp_dir)  # 手動で削除
```
temp_dir は一時ディレクトリのパスです。ディレクトリは自動的に削除されないため、手動で削除する必要があります。
<br><br>
- ### 6-7 `glob` --- パス名のパターン展開
`glob` モジュールは、ファイルシステム内のパス名のパターンマッチングを行うためのツールを提供します。このモジュールを使うと、指定したパターンに一致するファイルを簡単に取得することができます。特に、ワイルドカード（*、?、[] など）を使って、ファイル名のパターンを展開したり、ファイルの検索を行ったりする際に非常に便利です。

#### 主な機能
- **`glob.glob(pathname, recursive=False)`**: 指定したパターンに一致するファイル名のリストを返します。
　　　　
- **`glob.iglob((pathname, recursive=False)`**: glob.glob() と似ていますが、イテレータを返します（メモリ効率が良い）。
　　　　
- **`glob.escape(pathname)`**: 特殊文字（例えば、* や ?）をエスケープします。

パターンの詳細
- **`*`**: 任意の文字列（ゼロ個以上の文字）に一致します。
- **`?`**: 任意の1文字に一致します。
- **`[]`**: 指定された文字のいずれか1文字に一致します。
- **`[!...]`**: 指定された文字以外の1文字に一致します。
#### 利用例
1.指定したパターンに一致するファイルのリストを取得 (`glob.glob()`)

```python

import glob

# カレントディレクトリ内のすべてのテキストファイルをリスト
text_files = glob.glob('*.txt')
print(text_files)  # 例: ['file1.txt', 'file2.txt', 'notes.txt']
```
この例では、カレントディレクトリにあるすべての .txt ファイルを取得します。

2.サブディレクトリ内のファイルも検索 (** と recursive=True)

** を使うと、サブディレクトリ内も再帰的に検索することができます。recursive=True を指定する必要があります。

```python
import glob

# サブディレクトリも含めて、すべての Python ファイルを検索
python_files = glob.glob('**/*.py', recursive=True)
print(python_files)  # 例: ['dir1/script.py', 'dir2/another_script.py']
```
このコードでは、カレントディレクトリ以下のすべてのサブディレクトリを再帰的に検索し、すべての .py ファイルをリストアップします。

3.ファイル名の一部で検索 (*, ?, [] を使ったパターンマッチング)

ワイルドカードを使って、ファイル名の一部を指定して検索できます。

```python
import glob

# "data" で始まり、".csv" で終わるファイルを検索
csv_files = glob.glob('data*.csv')
print(csv_files)  # 例: ['data1.csv', 'data_report.csv']

# 任意の1文字で埋められるファイル
single_char_files = glob.glob('file?.txt')
print(single_char_files)  # 例: ['file1.txt', 'file2.txt']

# 数字のファイルを検索
digit_files = glob.glob('file[0-9].txt')
print(digit_files)  # 例: ['file1.txt', 'file2.txt']
```
data.csv は、「data」で始まり「.csv」で終わるすべてのファイルに一致します。
file?.txt は、任意の1文字（?）を含むファイル名に一致します。
file[0-9].txt は、file1.txt、file2.txt など、数字が1桁のファイル名に一致します。
　　　　　
4.イテレータを使ったパターンマッチング (`glob.iglob()`)

`glob.iglob()` は `glob.glob()` と似ていますが、リストではなくイテレータを返します。大量のファイルを検索する際には、メモリ効率が良くなります。

```python
import glob

# イテレータを使ってファイル名を順に処理
for file_name in glob.iglob('*.txt'):
    print(file_name)# 例: file1.txt, file2.txt, document.txt
```
この方法では、ファイル名を一度にすべてメモリに読み込まずに順次処理することができます。

5.エスケープ文字の使用 (`glob.escape()`)

特殊文字を含む文字列を検索したい場合、`glob.escape()` を使って、パターン内の特殊文字をエスケープできます。

```python
import glob

# 正規表現の特殊文字を含む文字列をエスケープ
pattern = glob.escape('file[1].txt')
print(pattern)  # 出力: 'file\[1\].txt'
```
これにより、[1] のような文字列を特殊文字としてではなく、普通の文字列として検索することができます。
<br><br>
- ### 6-8 `fnmatch` --- Unix ファイル名のパターンマッチ
`fnmatch` モジュールは、Unixスタイルのファイル名パターンマッチングを行うためのツールです。これは、ファイル名が指定したパターンに一致するかどうかを判定するために使われます。パターンには、ワイルドカード文字（*, ?, [] など）を使用できますが、`glob` モジュールのようなファイルパスを展開するのではなく、ファイル名自体を直接比較します。

#### 主な機能
- **`fnmatch.fnmatch()`**: ファイル名が指定されたパターンに一致するかどうかを判定します。
- **`fnmatch.fnmatchcase()`**: 大文字と小文字を区別して、ファイル名が指定されたパターンに一致するかどうかを判定します。
- **`fnmatch.filter()`**: 一致するファイル名だけをフィルタリングするための関数です。
　　　　　
パターンの詳細
- **`*`**: 任意の文字列（ゼロ個以上の文字）に一致します。
- **`?`**: 任意の1文字に一致します。
- **`[]`**: 指定された文字のいずれか1文字に一致します。
- **`[!]`**: 指定された文字以外の1文字に一致します。
#### 利用例
ファイル名がパターンに一致するかを判定 (`fnmatch.fnmatch()`)

`fnmatch.fnmatch()` は、ファイル名が指定されたパターンに一致するかどうかを判定します。通常、ワイルドカード（*、? など）を使ったパターンを指定します。

```python
import fnmatch

# ファイル名がパターンに一致するかどうかを確認
print(fnmatch.fnmatch('file1.txt', '*.txt'))  # True
print(fnmatch.fnmatch('file2.csv', '*.txt'))  # False
print(fnmatch.fnmatch('file3.txt', 'file?.txt'))  # True
```
この例では、'file1.txt' は *.txt パターンに一致するため True を返しますが、'file2.csv' は一致しないため False になります。'file3.txt' は、file?.txt というパターン（任意の1文字のファイル名）に一致します。

大文字と小文字を区別してファイル名を比較

`fnmatch.fnmatchcase()` は、大文字と小文字を区別してパターンマッチングを行います。通常の `fnmatch.fnmatch()` は、大文字と小文字を区別せずに比較を行いますが、`fnmatchcase()` は厳密に区別します。

```python
import fnmatch

print(fnmatch.fnmatchcase('File.TXT', '*.txt'))  # False
print(fnmatch.fnmatchcase('file.TXT', '*.txt'))  # True
```
この例では、`fnmatchcase()` は大文字と小文字を区別しているため、'File.TXT' は *.txt には一致しませんが、'file.TXT' は一致します。

ファイル名のリストから一致するファイルをフィルタリング (`fnmatch.filter()`)

`fnmatch.filter()` を使うと、ファイル名のリストから指定したパターンに一致するファイルだけをフィルタリングできます。

```python
import fnmatch

# ファイル名のリスト
files = ['data1.txt', 'data2.csv', 'notes.txt', 'image.png']

# '.txt' 拡張子のファイルをフィルタリング
txt_files = fnmatch.filter(files, '*.txt')
print(txt_files)  # ['data1.txt', 'notes.txt']
```
このコードでは、files のリストから *.txt に一致するファイル（data1.txt と notes.txt）だけを抽出しています。

:::note info
文字クラスの使用（[] と !）

[] を使って、文字クラス（例えば、特定の文字セットや範囲）に一致するファイル名を検索できます。また、! を使って特定の文字以外に一致させることもできます。
:::

```python
import fnmatch

# 1文字目が 'f' で、2文字目が 'i' または 'o' で始まるファイルを検索
print(fnmatch.fnmatch('file.txt', 'f[i,o]*'))  # True
print(fnmatch.fnmatch('foo.txt', 'f[i,o]*'))   # True
print(fnmatch.fnmatch('bar.txt', 'f[i,o]*'))   # False

# 'file1.txt' の場合、最初の1文字が 'f' でないと一致しない
print(fnmatch.fnmatch('file1.txt', 'f[!i]*'))  # False
```
この例では、f[i,o]* パターンに一致するファイル（file.txt と foo.txt）を検索していますが、f[!i]* では file1.txt が一致しないことがわかります。

ディレクトリ内のファイルに対するパターンマッチング

`fnmatch` モジュールはファイル名のパターンマッチングに使用されるため、ファイルシステム内のファイルのリスト（例えば、`os.listdir()` など）に対しても使うことができます。

```python
import os
import fnmatch

# カレントディレクトリのファイルを取得
files = os.listdir('.')

# '.txt' 拡張子のファイルをフィルタリング
txt_files = fnmatch.filter(files, '*.txt')
print(txt_files)
# ['file1.txt', 'file2.txt', 'document.txt']
```
ここでは、カレントディレクトリ内の .txt 拡張子を持つファイルをフィルタリングしています。
<br><br>
- ### 6-9 `linecache` --- テキストラインへのランダムアクセス
`linecache` モジュールは、テキストファイルの特定の行にランダムにアクセスするための便利なツールを提供します。このモジュールを使用すると、ファイルを一度読み込んでキャッシュすることで、指定した行を効率的に取得できるため、大きなファイルを扱う際にも便利です。

特に、エラーメッセージの表示や、ファイル内の特定の行を取り出したい場合に役立ちます。

#### 主な機能

- **`linecache.getline(filename, lineno)`**: 指定されたファイルと行番号に対応する行を返します。
　　　　　
- **`linecache.checkcache(filename(オプション引数))`**: 現在キャッシュされているファイルのキャッシュを確認します。
　　　　
- **`linecache.clearcache(filename(オプション引数))`**: キャッシュをクリアします。
　　　　
- **`linecache.getlines(filename)`**: ファイルのすべての行をリストとして取得します。
#### 利用例
1.特定の行を取得 (`linecache.getline()`)

`linecache.getline()` を使うことで、指定したファイルの特定の行を簡単に取得できます。ファイルは最初にキャッシュされるため、同じファイルに対して複数回アクセスする際に効率的です。

```python
import linecache

# ファイル 'example.txt' の3行目を取得
line = linecache.getline('example.txt', 3)
print(line) # example.txt の3行目を出力
```
この例では、example.txt の3行目を取得しています。ファイルはキャッシュされ、繰り返しアクセスしても効率的に行を取得できます。

2.キャッシュの確認 (`linecache.checkcache()`)

`linecache.checkcache()` を使って、現在キャッシュされているファイルの情報を確認できます。このメソッドは、キャッシュを更新するために使用することもできます。

```python
import linecache

# キャッシュの状態を確認
linecache.checkcache('example.txt')
```
これにより、example.txt に関連するキャッシュが確認され、必要に応じて再読み込みや更新が行われます。

3.キャッシュのクリア (`linecache.clearcache()`)

キャッシュをクリアするために linecache.clearcache() を使用できます。これにより、全てのキャッシュが削除され、次回アクセス時にファイルが再読み込みされます。

```python
import linecache

# キャッシュをクリア
`linecache.clearcache()`
```
4.全行を取得 (`linecache.getlines()`)

`linecache.getlines()` を使うと、指定したファイルの全行をリストとして取得できます。これは、ファイルの内容を一度に取得したいときに便利です。

```python
import linecache

# ファイル 'example.txt' の全行をリストとして取得
lines = linecache.getlines('example.txt')
for line in lines:
    print(line, end='')  # 各行を表示
```
このコードでは、example.txt の全ての行をリストとして取得し、各行を表示しています。

5.キャッシュの使用例

`linecache` モジュールは、一度読み込んだファイルの行をキャッシュするため、繰り返しファイルにアクセスする場合には、効率的に動作します。

```python
import linecache

# 最初の1行を取得
line1 = linecache.getline('example.txt', 1)
print("First line:", line1)

# 2回目のアクセスでキャッシュが使用される
line2 = linecache.getline('example.txt', 2)
print("Second line:", line2)

# キャッシュの状態を確認
linecache.checkcache('example.txt')
```
この例では、example.txt の1行目と2行目を順番に取得し、キャッシュされたファイルに対して効率的にアクセスしています。
<br><br>
- ### 6-10 `shutil` --- 高水準ファイル操作
`shutil` モジュールは、高水準のファイル操作を行うためのツールです。ファイルのコピー、移動、削除、ディレクトリの作成、圧縮・解凍など、ファイルやディレクトリに対する一般的な操作を簡単に行うことができます。

#### 主な機能

- **`shutil.copy(src, dst)`**: ファイルをコピー
　　　　
- **`shutil.move(src, dst)`**: ファイルまたはディレクトリの移動
　　　　
- **`shutil.rmtree(path, ignore_errors=False, onerror=None)`**:ディレクトリを削除
　　　　
- **`shutil.make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None)`**:
 圧縮ファイルを作成
　　　　
- **`shutil.unpack_archive(filename, extract_dir=None, format=None(オプション))`**: 圧縮ファイルを解凍

- **`shutil.disk_usage(path)`**: ディスクの使用状況を取得
　　　　
- **`shutil.chown(path, user=None, group=None)`**: ファイルの所有者やグループを変更
#### 利用例
:::note info
 ファイルのコピー
- **`shutil.copy()`**: コピー元のファイルをコピー先のパスにコピーします。元のファイルのメタデータ（タイムスタンプなど）はコピーされません。
- **`shutil.copy2()`**: `copy()` と同様ですが、元のファイルのメタデータ（作成時刻やアクセス時刻）もコピーします。
:::
```python
import shutil

# ファイルをコピー
shutil.copy('source.txt', 'destination.txt')

# メタデータもコピー
shutil.copy2('source.txt', 'destination_with_metadata.txt')
```
 ファイルやディレクトリの移動
`shutil.move()`: ファイルやディレクトリを指定した場所に移動します。移動先に同名のファイルが存在する場合は上書きされます。
```python
import shutil

# ファイルを移動
shutil.move('source.txt', 'new_folder/destination.txt')

# ディレクトリを移動
shutil.move('source_folder', 'destination_folder')
```
 ファイルやディレクトリの削除
`shutil.rmtree()`: ディレクトリを削除します。ディレクトリ内のファイルやサブディレクトリも再帰的に削除されます。
```python
import shutil

# ディレクトリを削除
shutil.rmtree('unnecessary_directory')
```
 ディレクトリの圧縮
`shutil.make_archive()`: 指定したディレクトリを圧縮してアーカイブファイルを作成します。圧縮形式には .zip, .tar, .gztar, .bztar などがサポートされています。
```python
import shutil

# ディレクトリをzip形式で圧縮
shutil.make_archive('archive_name', 'zip', 'folder_to_compress')
```
 圧縮ファイルの解凍
`shutil.unpack_archive()`: 圧縮されたアーカイブを指定した場所に解凍します。解凍形式に応じた解凍処理を行います（zip, tar, gzip など）。
```python
import shutil

# zip形式のアーカイブを解凍
shutil.unpack_archive('archive_name.zip', 'destination_folder')
```
 ディスクの使用状況を取得
`shutil.disk_usage()`: 指定したパスにあるディスクの使用状況（総容量、使用中の容量、空き容量）をタプルで返します。
```python
import shutil

# 現在のディレクトリのディスク使用状況を取得
usage = shutil.disk_usage('.')

print(f"Total: {usage.total / (1024 * 1024)} MB")
print(f"Used: {usage.used / (1024 * 1024)} MB")
print(f"Free: {usage.free / (1024 * 1024)} MB")
```
 ファイルの所有者やグループの変更
`shutil.chown()`: ファイルの所有者やグループを変更します。
```python
import shutil

# ファイルの所有者とグループを変更
shutil.chown('example.txt', user='new_user', group='new_group')
```

## 7. データの永続化
- ### 7-1 `pickle` --- Pythonオブジェクトの直列化
`pickle`はPythonでオブジェクトを直列化（シリアライズ）するためのモジュールです。オブジェクトをファイルやバイトストリームに変換して保存したり、後で復元（デシリアライズ）することができます。pickleを使うと、リストや辞書、クラスのインスタンスなど、Pythonのほとんどすべてのオブジェクトを保存することができます。


#### 主な関数
- **`pickle.dump(obj, file)`**: オブジェクト obj を file に直列化して保存します。
　　　　
- **`pickle.load(file)`**: 直列化されたデータからオブジェクトを復元します。
　　　　
- **`pickle.dumps(obj)`**: オブジェクト obj をバイトストリームに直列化します（ファイルを使わずにメモリ上で扱う場合）。
　　　　
- **`pickle.loads(bytes)`**: バイトストリームからオブジェクトを復元します。
例: pickleを使ったオブジェクトの保存と復元
```python
import pickle

# 保存するオブジェクト
data = {'name': 'Alice', 'age': 30, 'city': 'New York'}

# オブジェクトをファイルに直列化して保存
with open('data.pkl', 'wb') as f:
    pickle.dump(data, f)

# ファイルからオブジェクトを復元
with open('data.pkl', 'rb') as f:
    loaded_data = pickle.load(f)

print(loaded_data)
```

このコードでは、辞書オブジェクトdataをdata.pklというファイルに直列化して保存し、その後ファイルから読み込んで元の辞書オブジェクトに復元しています。

:::note warn
`pickle`はPython固有のフォーマットなので、他の言語ではデシリアライズできません。
セキュリティ上、信頼できないソースからのpickleデータを復元するのは危険です（任意のコードを実行する可能性があるため）。
:::

<br><br>
- ### 7-2 `copyreg` --- pickleサポート関数を登録する
Pythonの`copyreg`モジュールは、`pickle`モジュールでカスタムオブジェクトをシリアライズ（直列化）およびデシリアライズ（復元）するためのサポートを提供します。`copyreg`を使用することで、カスタムクラスや特定のオブジェクトのシリアライズ方法をカスタマイズできます。これにより、デフォルトのシリアライズ方法が適用できない場合でも、独自の方法でオブジェクトを保存・復元できるようになります。

#### 主な機能
- **`copyreg.pickle(type, reducer)`**: 
特定のオブジェクトタイプ type に対して、どのようにシリアライズするかを指定する `reducer` 関数を登録します。
　　　　
- **`copyreg.constructor(constructor)`**: 
クラスのインスタンスを復元するためのコンストラクタを登録します。これにより、シリアライズされたデータからオブジェクトを復元する際に、正しいインスタンスを作成することができます。
#### 利用例

```python
import copyreg
import pickle

# カスタムクラス
class MyClass:
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __repr__(self):
        return f"MyClass(name={self.name}, value={self.value})"

# シリアライズ方法を定義する関数
def pickle_myclass(obj):
    return MyClass, (obj.name, obj.value)

# MyClassに対してシリアライズ方法を登録
copyreg.pickle(MyClass, pickle_myclass)

# オブジェクトを作成
obj = MyClass("example", 42)

# pickleでシリアライズ
with open("myclass.pkl", "wb") as f:
    pickle.dump(obj, f)

# pickleで復元
with open("myclass.pkl", "rb") as f:
    loaded_obj = pickle.load(f)

print(loaded_obj)
```
#### 実行結果
```python
MyClass(name=example, value=42)
```
<br><br>
- ### 7-3 `shelve` --- Pythonオブジェクトの永続化
Pythonの`shleve`モジュールは、オブジェクトをディスクに永続化するためのシンプルで便利な方法を提供します。`shelve`を使うと、Pythonのオブジェクトを簡単にファイルに保存し、後でそのオブジェクトを復元することができます。

内部的には、`shelve`はPythonのdbmライブラリを使ってキーと値のペアとしてオブジェクトを保存します。これにより、辞書のようにオブジェクトをファイルに保存したり、キーでアクセスできるようになります。

#### 主な機能
- **`shelve.open(filename)`**: 
オブジェクトを保存するためのshelveデータベースを開きます。この関数は、指定したファイルにオブジェクトを永続化するためのインターフェースを提供します。
　
#### 利用例
`shleve`を使って、Pythonオブジェクトをファイルに保存し、その後復元する方法を示します。

```python
import shelve

# 保存するオブジェクト
data = {'name': 'Alice', 'age': 30, 'city': 'New York'}

# shelveを使ってオブジェクトをファイルに保存
with shelve.open('mydata.shelve') as shelf:
    shelf['user_info'] = data

# shelveからオブジェクトを復元
with shelve.open('mydata.shelve') as shelf:
    loaded_data = shelf['user_info']

print(loaded_data)
#出力:{'name': 'Alice', 'age': 30, 'city': 'New York'}
```
<br><br>
- ### 7-4 `marshal` --- 内部使用向けのオブジェクト直列化
Pythonの`marshal`モジュールは、主にPythonの内部で使用されるオブジェクトの直列化と復元を行うための機能を提供します。このモジュールは、Pythonインタープリターがコードオブジェクトやその他の内部データを保存する際に使用されることが多く、特にコンパイルされたバイトコード（.pycファイル）を保存するために利用されます。`marshal`は高速で効率的ですが、他のシリアライズ方法（例えばpickle）よりも互換性に関して制限があり、主に内部用途に限られます。

#### 主な機能
- **`marshal.dump(obj, file)`**: 
オブジェクト obj をファイルに直列化して保存します。ファイルはバイナリモードで開く必要があります。

- **`marshal.load(file)`**: ファイルから直列化されたオブジェクトを復元します。
　　　　
- **`marshal.dumps(obj)`**: 
オブジェクト obj をバイト列として直列化します（ファイルを使用しない場合）。
　　　　
- **`marshal.loads(bytes)`**: バイト列からオブジェクトを復元します。
#### 利用例
`marshal`を使うと、Pythonオブジェクトをファイルにシリアライズし、後でそのオブジェクトを復元することができます。以下はその具体例です。

```python
import marshal

# 保存するオブジェクト
data = {'name': 'Alice', 'age': 30, 'city': 'New York'}

# marshalを使ってオブジェクトをファイルに保存
with open('data.marshal', 'wb') as f:
    marshal.dump(data, f)

# marshalを使ってオブジェクトをファイルから復元
with open('data.marshal', 'rb') as f:
    loaded_data = marshal.load(f)
print(loaded_data)
#出力:{'name': 'Alice', 'age': 30, 'city': 'New York'}
```
<br><br>
- ### 7-5 `dbm` --- Unixデータベースへのインターフェース
`dbm`モジュールは、Unixシステム上で動作するデータベースファイルを扱うためのインターフェースを提供します。これを使うと、シンプルなキーとバリューのペアとしてデータを保存し、後で効率的にアクセスできるようにすることができます。`dbm`は、単純なキー・バリュー型のデータを保存するのに適しており、SQLデータベースよりも軽量で手軽に使えるため、小規模なデータ保存に便利です。
。

#### 主な機能
- **`dbm.open(filename, flag)`**: 
データベースを開き、指定したファイルに対するキー・バリュー型データベースを操作します。flagは開くモードを指定します（例えば'c'は新規作成、'r'は読み取り専用）。
　　　　
- **`dbm[key] = value`**: データベースにデータを保存します。keyはキー、valueはバリューです。
　　　　
- **`dbm[key]`**: キーでデータを取得します。
- **`del dbm[key]`**: キーを削除します。
- **`dbm.keys()`**: 保存されている全てのキーを取得します。
- **`dbm.close()`**: データベースファイルを閉じます。
#### 利用例

```python
import dbm

# dbmデータベースを開く（新規作成または既存ファイルを開く）
with dbm.open('mydbm', 'c') as db:
    # データの保存
    db['name'] = 'Alice'
    db['age'] = '30'
    db['city'] = 'New York'
    
    # データの取得
    print(db['name'])  # Alice
    print(db['age'])   # 30

    # キーの削除
    del db['city']
    
    # キーのリスト
    print(list(db.keys()))  # ['name', 'age']

# dbmデータベースが自動的に閉じられます
```
#### 実行結果
```python
Alice
30
['name', 'age']
```
<br><br>
- ### 7-6 `sqlite3` --- SQLiteデータベースインターフェース
Pythonの`sqlite3`モジュールは、SQLiteデータベースと連携するためのインターフェースを提供します。SQLiteはサーバーレスで軽量なSQLデータベースエンジンで、ファイルベースで動作するため、データベースの管理が簡単で、軽量なアプリケーションに最適です。このモジュールを使用すると、SQLiteデータベースに接続して、SQLクエリを実行し、データの操作（挿入、更新、削除、検索）が可能になります。

#### 主な機能
- **`sqlite3.connect(database)`**: 
SQLiteデータベースに接続します。databaseはファイル名で、指定されたファイルが存在しない場合は新しく作成されます。
　　　　
- **`connection.cursor()`**:
データベース操作を行うためのカーソルオブジェクトを作成します。
　　　　
- **`cursor.execute(sql)`**: SQL文を実行します。
　　　　
- **`connection.commit()`**: 変更をデータベースに保存します（挿入、更新、削除など）。
　　　　
- **`cursor.fetchall()`**: クエリの結果を全て取得します。
　　　　
- **`connection.close()`**: データベース接続を閉じます。
#### 利用例

```python
import sqlite3

# SQLiteデータベースに接続（なければ新規作成）
connection = sqlite3.connect('example.db')

# カーソルを作成
cursor = connection.cursor()

# テーブルの作成
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER NOT NULL
)
''')

# データの挿入
cursor.execute('''
INSERT INTO users (name, age)
VALUES ('Alice', 30), ('Bob', 25), ('Charlie', 35)
''')

# 変更をデータベースに反映
connection.commit()

# データをクエリして取得
cursor.execute('SELECT * FROM users')

# 結果を表示
for row in cursor.fetchall():
    print(row)

# データベース接続を閉じる
connection.close()
```
 実行結果
```python
(1, 'Alice', 30)
(2, 'Bob', 25)
(3, 'Charlie', 35)
```

## 8. データ圧縮とアーカイブ
- ### 8-1 `zlib` --- gzip互換の圧縮
Pythonの`zlib`モジュールは、圧縮および展開のためのモジュールです。主に、gzip圧縮形式との互換性があり、Deflateアルゴリズムを用いてデータの圧縮と展開を行います。このモジュールを使用すると、圧縮率を調整しつつ、バイナリデータやテキストデータを効率的に圧縮することができます。

#### 主な機能
- **`zlib.compress(data, level)`**: 指定したデータを圧縮します。
　　　　
- **`zlib.decompress(data)`**: 圧縮されたデータを元に戻します。
　　　　　
- **`zlib.crc32(data)`**: データのCRC32チェックサムを計算します。
　　　　　
- **`zlib.compressobj(data, level)`**: 
圧縮オブジェクトを生成し、ストリーム圧縮を実行します。
　　　　
- **`zlib.decompressobj(wbits, memLevel, strategy)`**: 
展開オブジェクトを生成し、ストリーム展開を実行します。
#### 利用例

```python
import zlib

# 圧縮したいデータ（バイト列）
data = b"Python is awesome! Python is fast and efficient!"

# データを圧縮
compressed_data = zlib.compress(data)

print(f"圧縮前のデータ: {data}")
#出力:圧縮前のデータ: b'Python is awesome! Python is fast and efficient!'

print(f"圧縮後のデータ: {compressed_data}")
#出力:圧縮後のデータ: b'x\x9c+I-.\x01\x00\x05\xd2\x02^'

# 圧縮されたデータを展開
decompressed_data = zlib.decompress(compressed_data)

print(f"展開後のデータ: {decompressed_data}")
#出力:展開後のデータ: b'Python is awesome! Python is fast and efficient!'

```

<br><br>
- ### 8-2 `gzip` --- gzipファイルのサポート
Pythonの`gzip`モジュールは、gzip圧縮されたファイルの読み書きをサポートします。gzipは、データを圧縮してファイルサイズを削減するためによく使われる形式であり、`gzip`モジュールを使用することで、gzipファイルの読み込みや書き込みが簡単に行えます。

#### 主な機能
- **`gzip.open(filename, mode)`**: 
gzipファイルを開きます。modeには、圧縮ファイルを読み込むために 'rb'（バイナリ読み込み）や、圧縮ファイルに書き込むために 'wb'（バイナリ書き込み）を指定します。
　　　　     
- **`gzip.GzipFile(filename, mode)`**: 
より低レベルのインターフェースでgzip圧縮ファイルを操作します。
  　　　　　   
- **`gzip.compress(data)`**: データをgzip形式で圧縮します。
　　　　　
- **`gzip.decompress(data)`**: gzip形式のデータを展開します。
#### 利用例

```python
import gzip

# 圧縮するデータ
data = b"Python is awesome! Python is fast and efficient!"

# gzipファイルに圧縮して書き込む
with gzip.open('example.gz', 'wb') as f:
    f.write(data)

print("データが圧縮されて 'example.gz' ファイルに書き込まれました。")
#出力:データが圧縮されて 'example.gz' ファイルに書き込まれました。

# gzipファイルを展開して読み込む
with gzip.open('example.gz', 'rb') as f:
    decompressed_data = f.read()

print(f"展開されたデータ: {decompressed_data}")
#出力:展開されたデータ: b'Python is awesome! Python is fast and efficient!'
```

<br><br>
- ### 8-3 `bz2` --- bzip2圧縮サポート
Pythonの`bz2`モジュールは、bzip2圧縮形式のデータを圧縮および展開できます。bzip2は、非常に高い圧縮率を提供する圧縮アルゴリズムで、ファイルのサイズを大きく削減するのに役立ちます。bz2モジュールを使うことで、bzip2形式でのファイル操作が簡単に行えます。

#### 主な機能
- **`bz2.BZ2File(filename, mode)`**: 
bzip2圧縮ファイルを開くためのインターフェースです。modeには、圧縮ファイルを読み込むために 'rb'（バイナリ読み込み）や、圧縮ファイルに書き込むために 'wb'（バイナリ書き込み）を指定します。
    　　　　
- **`bz2.compress(data)`**: データをbzip2形式で圧縮します。
　　　　
- **`bz2.decompress(data)`**: bzip2圧縮されたデータを展開します。
　　　　　
- **`bz2.open(filename, mode)`**:
圧縮されたファイルを開き、読み書きすることができます。
#### 利用例
```python
import bz2

# 圧縮するデータ
data = b"Python is awesome! Python is fast and efficient!"

# bzip2ファイルに圧縮して書き込む
with bz2.open('example.bz2', 'wb') as f:
    f.write(data)

print("データが圧縮されて 'example.bz2' ファイルに書き込まれました。")

# bzip2ファイルを展開して読み込む
with bz2.open('example.bz2', 'rb') as f:
    decompressed_data = f.read()

print(f"展開されたデータ: {decompressed_data}")
```
 実行結果
```python
データが圧縮されて 'example.bz2' ファイルに書き込まれました。
展開されたデータ: b'Python is awesome! Python is fast and efficient!'
```
<br><br>
- ### 8-4 `lzma` --- LZMAアルゴリズムを使用した圧縮
Pythonの`lzma`モジュールは、LZMA（Lempel-Ziv-Markov chain algorithm）圧縮アルゴリズムを使用してデータを圧縮および展開します。LZMAは非常に高い圧縮率を提供し、大容量のデータを効率的に圧縮するのに適しています。`lzma`モジュールは、ファイル操作を簡単に行い、圧縮されたデータを素早く扱うことができます。

#### 主な機能
- **`lzma.LZMAFile(filename, mode)`**: 
LZMA圧縮ファイルを開くインターフェース。modeには、圧縮ファイルを読み込むために 'rb'（バイナリ読み込み）や、圧縮ファイルに書き込むために 'wb'（バイナリ書き込み）を指定します。
　　　　
- **`lzma.compress(data)`**: データをLZMA圧縮形式で圧縮します。
　　　　
- **`lzma.decompress(data)`**: LZMA圧縮されたデータを展開します。
　　　　
- **`lzma.open(filename, mode)`**: 圧縮されたファイルを開いて、読み書きができます。
#### 利用例

```python
import lzma

# 圧縮するデータ
data = b"Python is awesome! LZMA is fast and efficient!"

# LZMAファイルに圧縮して書き込む
with lzma.open('example.lzma', 'wb') as f:
    f.write(data)

print("データが圧縮されて 'example.lzma' ファイルに書き込まれました。")

# LZMAファイルを展開して読み込む
with lzma.open('example.lzma', 'rb') as f:
    decompressed_data = f.read()

print(f"展開されたデータ: {decompressed_data}")
```
 実行結果
```python
データが圧縮されて 'example.lzma' ファイルに書き込まれました。
展開されたデータ: b'Python is awesome! LZMA is fast and efficient!'
```
<br><br>
- ### 8-5 `zipfile` --- ZIPアーカイブの処理
Pythonの`zipfile`モジュールは、ZIPアーカイブ（圧縮ファイル）を作成・読み取り・編集するためのインターフェースを提供します。これにより、Pythonから簡単にZIP形式のファイルを操作することができます。

#### 主な機能
- **`zipfile.ZipFile(filename, mode)`**: ZIPファイルを開き、指定されたモード（読み取り、書き込み、追加など）で操作します。
    - **`r`**: 読み取り専用
    - **`w`**: 新規作成（既存のアーカイブがあれば上書き）
    - **`a`**: 既存のアーカイブに追加
- **`zipfile.ZipFile.extractall(path)`**: アーカイブ内のすべてのファイルを指定されたディレクトリに展開します。
- **`zipfile.ZipFile.extract(member, path)`**: アーカイブ内の特定のファイルを展開します。
- **`zipfile.ZipFile.write(filename)`**: 指定したファイルをZIPアーカイブに追加します。
- **`zipfile.ZipFile.infolist()`**: アーカイブ内のファイル情報をリスト形式で取得します。
#### 利用例
1.ZIPファイルの作成
以下のコードでは、2つのファイル (file1.txt, file2.txt) をZIPアーカイブに圧縮しています。

```python
import zipfile

# ZIPファイルを作成（書き込みモード）
with zipfile.ZipFile('example.zip', 'w') as zipf:
    zipf.write('file1.txt')
    zipf.write('file2.txt')

print("ファイルが 'example.zip' に圧縮されました。")
#出力:ファイルが 'example.zip' に圧縮されました。
```
2.ZIPファイルの展開
以下のコードでは、ZIPファイル (example.zip) 内の全ファイルを指定したディレクトリ（extracted_files/）に展開します。

```python
import zipfile

# ZIPファイルを展開（展開先ディレクトリ指定）
with zipfile.ZipFile('example.zip', 'r') as zipf:
    zipf.extractall('extracted_files')

print("ファイルが 'extracted_files' フォルダに展開されました。")
#出力:ファイルが 'extracted_files' フォルダに展開されました。
```
3.ZIPファイル内のファイル情報を表示
ZIPアーカイブ内のファイル情報（名前や圧縮後のサイズなど）を取得する方法です。

```python
import zipfile

# ZIPファイル内のファイル情報をリスト表示
with zipfile.ZipFile('example.zip', 'r') as zipf:
    file_list = zipf.infolist()
    for file in file_list:
        print(f"ファイル名: {file.filename}, サイズ: {file.file_size} バイト")
        #出力:ファイル名: file1.txt, サイズ: 1024 バイト
        #出力:ファイル名: file2.txt, サイズ: 2048 バイト
```

<br><br>
- ### 8-6 `tarfile` --- tarアーカイブファイルの読み書き
Pythonの`tarfile`モジュールは、tarアーカイブ（.tar）を操作するためのインターフェースを提供します。このモジュールを使用すると、tarファイルを作成したり、展開したり、アーカイブの内容を確認したりすることができます。tarfileは、tar形式で圧縮されたファイル（gzipやbzip2などを使った圧縮）にも対応しています。

#### 主な機能
- **`tarfile.open(name, mode)`**: 指定されたモード（r、w、a）でtarファイルを開きます。
　　　　
- **`tarfile.TarFile.getnames()`**: アーカイブ内のすべてのファイル名をリストとして取得します。
　　　　
- **`tarfile.TarFile.extractall(path)`**: 
- アーカイブ内のすべてのファイルを指定されたディレクトリに展開します。
　　　　
- **`tarfile.TarFile.extract(name, path)`**: 指定したファイルを展開します。
　　　　
- **`tarfile.TarFile.add(name)`**: ファイルをアーカイブに追加します。
　　　　
- **`tarfile.TarFile.getmembers()`**: アーカイブ内のファイルメンバー情報を取得します。
#### 利用例
1.Tarアーカイブの作成
以下のコードでは、複数のファイル (file1.txt と file2.txt) をtarアーカイブに圧縮します。

```python
import tarfile

# tarファイルを作成（書き込みモード）
with tarfile.open('example.tar', 'w') as tarf:
    tarf.add('file1.txt')  # file1.txtをアーカイブに追加
    tarf.add('file2.txt')  # file2.txtをアーカイブに追加

print("ファイルが 'example.tar' に圧縮されました。")
#出力:ファイルが 'example.tar' に圧縮されました。
```
2.Tarアーカイブの展開
以下のコードでは、作成したtarアーカイブ（example.tar）内のすべてのファイルを指定したディレクトリに展開します。

```python
import tarfile

# tarファイルを展開（展開先ディレクトリ指定）
with tarfile.open('example.tar', 'r') as tarf:
    tarf.extractall('extracted_files')  # extracted_filesディレクトリに展開

print("ファイルが 'extracted_files' フォルダに展開されました。")
#出力:ファイルが 'extracted_files' フォルダに展開されました。
```
3.Tarアーカイブ内のファイルリストを表示
tarファイル内に格納されているファイルのリストを表示する方法です。

```python
import tarfile

# tarファイルを読み取りモードで開く
with tarfile.open('example.tar', 'r') as tarf:
    members = tarf.getnames()  # アーカイブ内のファイル名を取得
    print("アーカイブ内のファイル:")
    for member in members:
        print(member)
        #出力:アーカイブ内のファイル:
        #      file1.txt
        #      file2.txt
```


## 9. ファイルフォーマット
- ### 9-1 `csv` --- CSVファイルの読み書き
Pythonの`csv`モジュールは、CSV（Comma Separated Values）形式のファイルを簡単に読み書きするためのツールです。CSVは、データをコンマで区切った形式で格納するファイル形式で、データの交換に広く利用されています。このモジュールは、CSVファイルの操作をシンプルに行えるように設計されています。

#### 主な機能
- **`csv.reader(file)`**: CSVファイルを読み込み、行単位でデータを取得します。
　　　　
- **`csv.writer(file)`**: CSVファイルにデータを書き込みます。
　　　　
- **`csv.DictReader(file)`**: CSVファイルを辞書形式で読み込みます（ヘッダー行をキーとして使用）。
　　　　
- **`csv.DictWriter(file)`**: 辞書形式でCSVファイルに書き込みます。
#### 利用例
1. CSVファイルの読み込み
以下のコードは、CSVファイルを読み込んでその内容を行ごとに出力する方法です。

```python
import csv

# CSVファイルを読み込みモードで開く
with open('sample.csv', mode='r', newline='') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)  # 行ごとにデータを出力
```
2.CSVファイルの書き込み
次のコードは、リストのデータをCSVファイルに書き込む方法です。

```python
import csv

# 書き込みモードでCSVファイルを開く
with open('output.csv', mode='w', newline='') as file:
    writer = csv.writer(file)
    # ヘッダーを書き込む
    writer.writerow(['名前', '年齢', '職業'])
    # データ行を書き込む
    writer.writerow(['田中', 28, 'エンジニア'])
    writer.writerow(['佐藤', 35, 'デザイナー'])
```
3.辞書形式でCSVファイルの読み書き
csv.DictReaderとcsv.DictWriterを使うと、ヘッダー行をキーとして扱い、より扱いやすい辞書形式でデータを読み書きできます。

読み込み（辞書形式）
```python
import csv

# CSVファイルを辞書形式で読み込む
with open('sample.csv', mode='r', newline='') as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(row)  # 各行を辞書形式で表示
```
書き込み（辞書形式）
```python
import csv

# CSVファイルを辞書形式で書き込む
with open('output.csv', mode='w', newline='') as file:
    fieldnames = ['名前', '年齢', '職業']
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()  # ヘッダー行を書き込む
    # 辞書形式でデータを書き込む
    writer.writerow({'名前': '田中', '年齢': 28, '職業': 'エンジニア'})
    writer.writerow({'名前': '佐藤', '年齢': 35, '職業': 'デザイナー'})
```
<br><br>
- ### 9-2 `configparser` --- 設定ファイルのパーサー
Pythonの`configparser`モジュールは、設定ファイル（通常は.ini形式）を読み書きするためのライブラリです。設定ファイルは、ソフトウェアの設定やユーザー設定を保存するために広く使われる形式で、セクションとキー・バリューのペアで構成されます。configparserはこれらの設定ファイルを簡単に扱うための機能を提供します。

#### 主な機能
- **`configparser.ConfigParser()`**: 設定ファイルの読み書き、解析、管理を行うクラス。
　　　　
- **`read(filename)`**: 設定ファイルを読み込む。
　　　　
- **`get(section, option)`**: セクションとキーから値を取得する。
　　　　
- **`set(section, option, value)`**: セクションとキーに値を設定する。
　　　　
- **`write(file)`**: 設定ファイルに書き込む。
#### 利用例
1.設定ファイルの読み込み
まず、`vconfigparser`モジュールを使って設定ファイルを読み込み、特定のセクションやキーから設定を取得します。

```ini
# sample.ini
[general]
app_name = MyApp
version = 1.0

[database]
host = localhost
port = 3306
user = admin
password = secret
```
```python
import configparser

# ConfigParserインスタンスの作成
config = configparser.ConfigParser()

# 設定ファイルの読み込み
config.read('sample.ini')

# 設定の取得
app_name = config.get('general', 'app_name')
db_host = config.get('database', 'host')
db_port = config.getint('database', 'port')  # 整数として取得

print(f"App Name: {app_name}")
print(f"Database Host: {db_host}")
print(f"Database Port: {db_port}")
#出力:App Name: MyApp
#出力:Database Host: localhost
#出力:Database Port: 3306
```


2.設定ファイルへの書き込み
`configparser`を使って設定ファイルに新しい設定を書き込む方法です。

```python
import configparser

# ConfigParserインスタンスの作成
config = configparser.ConfigParser()

# 設定の設定
config['general'] = {
    'app_name': 'MyNewApp',
    'version': '2.0'
}

config['database'] = {
    'host': '127.0.0.1',
    'port': '5432',
    'user': 'root',
    'password': 'newpassword'
}

# 設定ファイルへの書き込み
with open('new_config.ini', 'w') as configfile:
    config.write(configfile)
```
3.セクションとキーの存在確認
指定したセクションやキーが存在するかをチェックする方法です。

```python
import configparser

config = configparser.ConfigParser()
config.read('sample.ini')

# セクションの存在確認
if config.has_section('database'):
    print("Database section exists")
    #出力:Database section exists

# キーの存在確認
if config.has_option('general', 'app_name'):
    print("App name is defined")
    #出力:App name is defined
```

<br><br>
- ### 9-3 `tomllib` --- TOMLファイルの解析
`tomllib`はPython 3.11以降に追加された標準ライブラリで、TOML（Tom's Obvious, Minimal Language）ファイルを簡単に解析するためのモジュールです。TOMLは、設定ファイルフォーマットとして広く使われており、PythonやRustなどでよく見かけます。

#### 主な機能

- **`tomllib.loads(s: str) -> dict`**: 
TOML文字列を解析してPythonの辞書（dict）に変換。
　　　　
- **`tomllib.load(f: IO) -> dict`**: 
ファイルからTOMLデータを読み込み、辞書形式で返す。
TOMLデータのシンプルで直感的な解析。
#### 利用例
1.TOMLファイルの解析
```toml
# example.toml
[server]
address = "127.0.0.1"
port = 8080

[database]
user = "admin"
password = "secret"
```
```python
import tomllib

# TOMLファイルを読み込む
with open('example.toml', 'rb') as f:  # ファイルはバイナリモードで開く
    toml_data = tomllib.load(f)

# 取得したデータを表示
print(toml_data) # 出力例: {'server': {'address': '127.0.0.1', 'port': 8080}, 'database': {'user': 'admin', 'password': 'secret'}}

# サーバーのアドレスとポートを取得
server_address = toml_data['server']['address']
server_port = toml_data['server']['port']

print(f"Server address: {server_address}")# 出力例: Server address: 127.0.0.1
print(f"Server port: {server_port}")# 出力例: Server port: 8080

```
2.TOML文字列を直接解析
```python
import tomllib

toml_string = """
[server]
address = "127.0.0.1"
port = 8080

[database]
user = "admin"
password = "secret"
"""

# TOML文字列を解析
toml_data = tomllib.loads(toml_string)

# データの取得
server_address = toml_data['server']['address']
server_port = toml_data['server']['port']

print(f"Server address: {server_address}")# 出力例: Server address: 127.0.0.1
print(f"Server port: {server_port}") # 出力例: Server port: 8080
```
<br><br>
- ### 9-4 `netrc` --- netrcファイルの処理
`netrc`モジュールは、Unix系システムにおけるnetrcファイルの処理を支援するためのライブラリです。netrcファイルは、ユーザーのログイン情報（ユーザー名、パスワードなど）を保存するためのファイルで、FTPクライアントやその他のネットワークツールによく使用されます。

このモジュールを使うと、netrcファイルを簡単に読み込み、認証情報を抽出することができます。

#### 主な機能
- **`netrc.Netrc(file=None)`**: 
netrcファイルを解析し、認証情報（ユーザー名、パスワードなど）を取得。
　　　　
- **`netrc.Netrc.parse(file(必須))`**: 
ファイルまたは文字列からnetrc情報を解析して、Netrcオブジェクトを作成。
　　　　　
- **`Netrc.authenticators(hostname)`**: サーバーの認証情報を取得。
　　　　
- **`Netrc.hosts()`**: サーバー情報を抽出するメソッド。
#### 利用例
1.netrcファイルの解析
まず、以下のようなnetrcファイルがあるとします：

```
machine example.com
  login myusername
  password mypassword

machine ftp.example.org
  login user2
  password password2
```
2.Pythonコードでの使用
```python
import netrc

# netrcファイルを解析する
netrc_file = netrc.netrc()  # デフォルトのnetrcファイル（~/.netrc）を読み込む

# 特定のマシンに対する認証情報を取得する
auth_info = netrc_file.authenticators("example.com")

# 認証情報を表示
if auth_info:
    login, _, password = auth_info
    print(f"Login: {login}")        # 出力例: Login: myusername
    print(f"Password: {password}")  # 出力例: Password: mypassword
else:
    print("No authentication information found.")
    # 出力例:No authentication information found.

```
3.netrcファイルの読み込みとエラーハンドリング
```python
import netrc

# 存在しないファイルを指定するとエラーが発生します
try:
    netrc_file = netrc.netrc("non_existing_file.netrc")
except FileNotFoundError:
    print("netrc file not found.")
    #出力:netrc file not found.
except netrc.NetrcParseError as e:
    print(f"Error parsing netrc file: {e}")
    # 出力:Error parsing netrc file: [詳細なエラーメッセージ]
```
4.netrcファイルのカスタム解析
```python
import netrc

# カスタムファイルを指定して解析
try:
    netrc_file = netrc.netrc("/path/to/custom/netrc")
    auth_info = netrc_file.authenticators("ftp.example.org")
    if auth_info:
        login, _, password = auth_info
        print(f"FTP Login: {login}")   # 出力例: FTP Login: user2
        print(f"FTP Password: {password}")  # 出力例: FTP Password: password2
    else:
        print("No authentication information for ftp.example.org")
        #出力: Custom netrc file not found.
except FileNotFoundError:
    print("Custom netrc file not found.")
    #出力:No authentication information for ftp.example.org
```

 - ### 9-5 `plistlib` --- Apple .plistファイルを生成・解析
 `plistlib`は、AppleのProperty List（.plist）ファイルを操作できます。このライブラリは、.plistファイル（XMLまたはバイナリ形式）を読み書きするための機能を提供します。.plistファイルは、設定情報やアプリケーションの状態、ユーザー設定などを保存するために広く使用されます。

#### 主な機能
- **`plistlib.load(file)`**: .plistファイルの読み込み。
　
- **`plistlib.dump(obj, file, protocol=None)`**: 
Pythonオブジェクトを.plistファイルに書き込む。
　　　　
- **`plistlib.loads(plist_data)`**: .plist形式のバイナリデータを読み込む。
　　　　
- **`plistlib.dumps(obj)`**: Pythonオブジェクトを.plist形式のバイナリデータに変換。
#### 利用例
1. .plistファイルの読み込み
まず、以下のようなXML形式の.plistファイルがあるとします（例: settings.plist）：

```xml
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>username</key>
    <string>john_doe</string>
    <key>email</key>
    <string>john.doe@example.com</string>
    <key>is_admin</key>
    <true/>
</dict>
</plist>
```
2.Pythonコードで.plistファイルを読み込む
```python
import plistlib

# plistファイルを読み込む
with open('settings.plist', 'rb') as file:
    data = plistlib.load(file)

# 読み込んだ内容を表示
print(data)
#出力:{'username': 'john_doe', 'email': 'john.doe@example.com', 'is_admin': True}
```

3.Pythonオブジェクトを.plistファイルに書き込む
次に、Pythonの辞書型オブジェクトを.plistファイルに書き込む方法です。

```python
import plistlib

# 保存するデータ
data = {
    'username': 'alice_smith',
    'email': 'alice.smith@example.com',
    'is_admin': False
}

# plistファイルに書き込む
with open('new_settings.plist', 'wb') as file:
    plistlib.dump(data, file)
```
4..plist形式のバイナリデータを読み書きする
plistlibは、バイナリ形式の.plistファイルにも対応しています。次の例では、Pythonオブジェクトをバイナリ形式で保存し、再び読み込む方法を示します。

```python
import plistlib

# Pythonオブジェクト
data = {
    'username': 'bob_jones',
    'email': 'bob.jones@example.com',
    'is_admin': True
}

# バイナリ形式で保存
with open('settings_binary.plist', 'wb') as file:
    plistlib.dump(data, file, fmt=plistlib.FMT_BINARY)

# バイナリファイルを読み込む
with open('settings_binary.plist', 'rb') as file:
    binary_data = plistlib.load(file)

# 読み込んだデータを表示
print(binary_data)
#出力:{'username': 'bob_jones', 'email': 'bob.jones@example.com', 'is_admin': True}
```

5.バイナリデータを直接扱う
listlibでは、バイナリデータを直接メモリ内で処理することもできます。

```python
import plistlib

# Pythonオブジェクト
data = {
    'username': 'charlie_brown',
    'email': 'charlie.brown@example.com',
    'is_admin': True
}

# オブジェクトをバイナリ形式に変換
binary_data = plistlib.dumps(data, fmt=plistlib.FMT_BINARY)

# バイナリデータを読み込む
loaded_data = plistlib.loads(binary_data)

# 読み込んだデータを表示
print(loaded_data)
#出力:{'username': 'charlie_brown', 'email': 'charlie.brown@example.com', 'is_admin': True}
```


 ## 10. 暗号関連サービス
- ### 10-1 `hashlib` --- セキュアハッシュとメッセージダイジェスト
`hashlib`モジュールは、セキュアなハッシュアルゴリズム（SHA, MD5 など）を使って、メッセージダイジェスト（ハッシュ値）を計算できます。

:::note info
データの整合性確認、パスワードのハッシュ化、デジタル署名などに使用されるハッシュ値を簡単に取得できます。
:::
#### 主な機能

- **`hashlib.md5()`**: 
MD5アルゴリズムを使用して、128ビットのハッシュ値を生成します。セキュリティ上、衝突攻撃に弱いため、重要な用途には使用しない方が良いとされています。
   　　　　
- **`hashlib.sha1()`**: 
SHA-1アルゴリズムを使用して、160ビットのハッシュ値を生成します。こちらも衝突攻撃に対して脆弱であり、安全なアプリケーションでは使用が推奨されません。
　　　　　
- **`hashlib.sha256()`**: 
SHA-256アルゴリズムを使用して、256ビットのハッシュ値を生成します。安全性が高く、現在最も広く使われているハッシュアルゴリズムの一つです。
　　　　　
- **`hashlib.sha512()`**: 
SHA-512アルゴリズムを使用して、512ビットのハッシュ値を生成します。SHA-256よりも長いハッシュ値が必要な場合に利用されます。
　　　　　
- **`hashlib.new()`**: 
任意のハッシュアルゴリズム（例えば、sha512 や sha3_256 など）を指定して、新しいハッシュオブジェクトを作成できます。これにより、標準でサポートされていないアルゴリズムも利用可能です。
　　　　　
- **`hashlib.algorithms_guaranteed`**: 
サポートされているすべてのハッシュアルゴリズムをリストとして取得することができます。
#### 利用例
文字列のハッシュ化
例えば、文字列をSHA-256アルゴリズムでハッシュ化する方法です。

```python
import hashlib

# ハッシュ化したい文字列
data = "Hello, world!"

# SHA-256でハッシュを計算
hash_object = hashlib.sha256()
hash_object.update(data.encode())  # 文字列をバイト列に変換して渡す
hashed_data = hash_object.hexdigest()  # ハッシュ値を16進数で取得

# 結果を表示
print(f"SHA-256 Hash: {hashed_data}")
#出力:SHA-256 Hash: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
```

複数回ハッシュする場合
データを逐次的にハッシュ化する場合の例です。例えば、長いデータをいくつかの部分に分けて、順次ハッシュしていくことができます。

```python
import hashlib

# ハッシュ化するデータのパーツ
data_parts = ["Hello", ", ", "world", "!"]

# SHA-256ハッシュオブジェクトを作成
hash_object = hashlib.sha256()

# データを逐次的にハッシュ
for part in data_parts:
    hash_object.update(part.encode())

# ハッシュ値を取得
hashed_data = hash_object.hexdigest()

# 結果を表示
print(f"SHA-256 Hash: {hashed_data}")
#出力:SHA-256 Hash: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda25307f98c7e5a3f9a7f
```


MD5でのハッシュ化
MD5は広く使われているアルゴリズムですが、セキュリティ上の理由からパスワードのハッシュ化には適していません。それでも簡単な検証やデータの整合性確認には利用されます。

```python
import hashlib

# ハッシュ化したい文字列
data = "Hello, world!"

# MD5でハッシュを計算
md5_hash = hashlib.md5()
md5_hash.update(data.encode())  # 文字列をバイト列に変換
hashed_md5 = md5_hash.hexdigest()

# 結果を表示
print(f"MD5 Hash: {hashed_md5}")
#出力:MD5 Hash: fc3ff98e8c6a0d3087d515c0473f8677
```
 
SHA-512でのハッシュ化
SHA-512を使用してデータをハッシュ化する方法です。

```python
import hashlib

# ハッシュ化したい文字列
data = "Hello, world!"

# SHA-512でハッシュを計算
sha512_hash = hashlib.sha512()
sha512_hash.update(data.encode())  # 文字列をバイト列に変換
hashed_sha512 = sha512_hash.hexdigest()

# 結果を表示
print(f"SHA-512 Hash: {hashed_sha512}")
#出力:SHA-512 Hash: 861844d6704e8573fec34d3586e3bfad58d540b24c43cc4a7d8a410c56b13602ed8f38d68d5b3d243db20a5bcde09728b1e01ae2b8e519ed41d0b290f5c92f43
```
 
<br><br>
- ### 10-2 `hmac` --- メッセージ認証用ハッシュ
`hmac（Hash-based Message Authentication Code）`は、メッセージの認証とデータの整合性を保証するための暗号学的な手法です。`hmac`モジュールは、秘密鍵を使用してハッシュ化されたメッセージ認証コード（MAC）を生成します。このコードを使用することで、メッセージが送信者によって変更されていないか、または偽造されていないかを検証できます。

:::note info
`hmac`は、データの認証を行うために広く利用されており、特に安全な通信を確保するために使用されます。例えば、API認証や署名付きリクエストなどで利用されます。
:::
#### 主な機能
- **`hmac.new(key, msg, digestmod)`**: 指定したキーとメッセージを使って、指定したハッシュアルゴリズム（digestmod）でHMACを生成します。
　　　　
- **`hmac.compare_digest(digest1, digest2)`**: 2つのHMAC認証コードを比較します。タイミング攻撃に対して安全です。
　　　　
- **`hmac.update(msg)`** : HMACオブジェクトにメッセージの一部を追加します。データを逐次的にハッシュしたい場合に使用します。
　　　　
- **`hmac.hexdigest()`**: HMACオブジェクトの最終的な認証コードを16進数の文字列として取得します。

#### 利用例
1. HMACを使った認証コードの生成
以下のコードは、hmacモジュールを使用してSHA-256アルゴリズムでメッセージ認証コード（MAC）を生成する例です。

```python
import hmac
import hashlib

# 使用する秘密鍵
secret_key = b"supersecretkey"

# ハッシュ化したいメッセージ
message = b"Hello, world!"

# HMACをSHA-256で生成
hmac_object = hmac.new(secret_key, message, hashlib.sha256)

# メッセージ認証コード（MAC）を16進数で表示
hmac_code = hmac_object.hexdigest()

print(f"HMAC: {hmac_code}")
#出力:HMAC: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b167eb54b300f6f6c02ef11e9e50261
```
 
2.HMACを使った認証と検証
送信者と受信者が秘密鍵を共有しており、受信者がメッセージの整合性を検証する場合、受信者は同じ秘密鍵を使用してHMACを生成し、それが送信者から受け取ったHMACと一致するかを確認します。

```python
import hmac
import hashlib

# 秘密鍵とメッセージ
secret_key = b"sharedsecretkey"
message = b"Important message!"

# 送信者が生成したHMAC
sender_hmac = hmac.new(secret_key, message, hashlib.sha256).hexdigest()

# 受信者が検証
received_message = b"Important message!"  # 受信したメッセージ
received_hmac = hmac.new(secret_key, received_message, hashlib.sha256).hexdigest()

if hmac.compare_digest(sender_hmac, received_hmac):
    print("メッセージは正当です。")
    #出力:メッセージは正当です。
else:
    print("メッセージは改ざんされています。")
```

3.異なるメッセージの検証
もしメッセージが改ざんされていた場合、HMACコードが一致しないため、受信者はそれを検出することができます。

```python
import hmac
import hashlib

# 秘密鍵とメッセージ
secret_key = b"sharedsecretkey"
original_message = b"Important message!"
tampered_message = b"Tampered message!"

# 送信者が生成したHMAC
sender_hmac = hmac.new(secret_key, original_message, hashlib.sha256).hexdigest()

# 受信者が検証（改ざんされたメッセージを受け取る）
received_hmac = hmac.new(secret_key, tampered_message, hashlib.sha256).hexdigest()

if hmac.compare_digest(sender_hmac, received_hmac):
    print("メッセージは正当です。")
   
else:
    print("メッセージは改ざんされています。")
    #出力:メッセージは改ざんされています。
```

<br><br>
- ### 10-3 `secrets` --- 機密データ用の安全な乱数生成
`secrets`モジュールは、機密データを扱う際に使用するための安全な乱数生成を提供します。これは、暗号学的に強力な乱数を生成するため、パスワードやトークン、セッションIDなど、セキュリティが求められる場面で非常に有用です。

#### 主な機能
- **`secrets.randbelow(n)`**: n より小さい整数（0 <= x < n）を生成します。暗号学的に安全な乱数を生成するため、セキュリティが重要な場面で利用されます。

- **`secrets.randbytes(n)`**: n バイトのランダムなバイト列を生成します。この関数は、セキュアなキーやトークンの生成に使用されます。

- **`secrets.choice(sequence)`**: シーケンス（リスト、タプル、文字列など）からランダムな要素を安全に選びます。パスワードや認証トークンの生成に役立ちます。

- **`secrets.token_bytes(n)`**: n バイトのランダムなトークンを生成します。セキュリティトークン、セッションIDなどの生成に使用されます。

- **`secrets.token_hex(n)`**: n バイトのランダムなトークンを16進数で生成します。例えば、セッションIDや認証トークンの生成に使われます。

- **`secrets.token_urlsafe(n)`**: URLセーフなランダムトークンを生成します。URLに埋め込むトークンなどに利用できます。

#### 利用例 

1. 安全な乱数生成
```python
import secrets

# 256ビットのランダムなバイト列を生成
random_bytes = secrets.token_bytes(32)

# 16進数で表示
print(random_bytes.hex())
#出力:91a1f1f876dfc3b462b48b6a61f97c4d9d2337d45d16e55081b0bc9c04d993e4
```
 
2.安全なパスワード生成
```python
import secrets
import string

# 使用する文字のセット（英大文字、英小文字、数字、記号）
alphabet = string.ascii_letters + string.digits + string.punctuation

# 12文字のランダムなパスワードを生成
password = ''.join(secrets.choice(alphabet) for _ in range(12))

print(password)
#出力:f1S!nPz0&yW9
```
 
3.セッションIDの生成
```python
import secrets

# 32文字のセッションIDを生成
session_id = secrets.token_hex(16)

print(session_id)
#出力:f5c9a4b8f2d7cfeabf8b9cd14942023f
```
 
4.認証用トークンの生成
```python
import secrets

# 64ビットのランダムなトークンを生成
token = secrets.token_urlsafe(32)

print(token)
#出力:TkFkd7dp8GRwMk0fLgFZBQJHZm3EtyhFPQ5R
```


## 11. 汎用オペレーティングシステムサービス
- ### 11-1 `os` --- OSインターフェース
`os` モジュールは、オペレーティングシステムとのやりとりを行うことができ、ファイルシステムの操作や環境変数、プロセス管理など、OS関連のさまざまな操作をサポートします。

#### 主な機能
- **`os.getcwd()`**, 現在の作業ディレクトリを取得します。
　　　　
- **`os.makedirs(name, mode=0o777, exist_ok=False)`**:
新しいディレクトリを作成します。
　　　　
- **`os.getenv(key, default=None)`**: 環境変数を取得します。
　　　　
- **`os.remove(path)`**: ファイルを削除します。
　　　　
- **`os.path.join(path, *paths)`**: 複数のパスを結合します。
　　　　
- **`os.path.basename(path)`**: パスからファイル名を取得します。
　　　　
- **`os.path.dirname(path)`**: パスからディレクトリ名を取得します。
　　　　
- **`os.system(command)`**: シェルコマンドを実行します。
　　　　
- **`os.name()`**: 使用しているオペレーティングシステムの名前を取得します。
#### 利用例
 カレントディレクトリの取得
```python
import os

# 現在の作業ディレクトリを取得
current_directory = os.getcwd()
print("Current Directory:", current_directory)
出力:Current Directory: /Users/username/projects
```

 ディレクトリの作成
```python
import os

# 新しいディレクトリを作成
os.makedirs('new_folder', exist_ok=True)  # exist_ok=Trueで既に存在してもエラーにならない
print("Directory 'new_folder' created.")
#出力:Directory 'new_folder' created.
```
 
 環境変数の取得
```python
import os

# 環境変数を取得
home_directory = os.getenv('HOME')
print("Home Directory:", home_directory)
#出力:Home Directory: /Users/username
```
 
 ファイルの削除
```python
import os

# ファイルを削除
os.remove('sample.txt')
print("File 'sample.txt' deleted.")
#出力:File 'sample.txt' deleted.
```
 
 ファイルパスの操作
```python
import os

# パスを結合する
file_path = os.path.join('folder', 'subfolder', 'file.txt')
print("Joined Path:", file_path)
#出力:Joined Path: folder/subfolder/file.txt


# ファイル名を取得
base_name = os.path.basename(file_path)
print("Base Name:", base_name)
#出力:Base Name: file.txt


# ディレクトリ名を取得
dir_name = os.path.dirname(file_path)
print("Directory Name:", dir_name)
#出力:Directory Name: folder/subfolder

```
 
 プロセスの実行
```python
import os

# コマンドを実行してプロセスを立ち上げる
exit_code = os.system('echo Hello, World!')
print("Exit Code:", exit_code)
#出力: Hello, World!
#      Exit Code: 0
```
 
 システム情報の取得
```python
import os
# システムのプラットフォームを取得
platform = os.name
print("Platform:", platform)
#出力:Platform: posix
```
 

- ### 11-2 `io` --- ストリーム操作
`io` モジュールは、Pythonにおけるストリーム操作（ファイルやデータの読み書き）をサポートするモジュールで、テキストファイルやバイナリファイルの読み書きを効率的に行うためのインターフェースを提供します。

#### 主な機能
- **`io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)`**: 
ファイルを開いて、指定されたモードで操作を行う。
　　　　　
- **`io.BytesIO(initial_bytes=b'')`**:
メモリ内でバイナリデータの読み書きを行うためのバッファ。
　　　　
- **`io.StringIO(initial_value='')`**:
メモリ内で文字列データの読み書きを行うためのバッファ。
　　　　
- **`io.BufferedReader(buffer(必須))`**:
バッファ付きの読み取り用ストリームを作成。通常はファイルやソケットなどからデータを読み取るために使用します。
　　　　
- **`io.BufferedWriter(buffer(必須))`**:
バッファ付きの書き込み用ストリームを作成。通常はファイルやソケットなどにデータを書き込むために使用します。
　　　　
- **`io.TextIOWrapper(buffer(必須), encoding='utf-8', errors=None, newline=None)`**:
バイナリデータの読み書きに加えて、テキストデータとしてエンコーディングされたストリーム操作を提供。


#### 利用例
1. テキストファイルの読み書き
```python
import io

# テキストファイルに書き込む
with io.open('example.txt', 'w', encoding='utf-8') as file:
    file.write("Hello, World!\nPython is awesome!")

# テキストファイルから読み込む
with io.open('example.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print(content)
```
出力
```
Hello, World!
Python is awesome!
```

2.バイナリファイルの読み書き
```python
import io

# バイナリデータをファイルに書き込む
with io.open('example.bin', 'wb') as file:
    file.write(b'Hello, World!')

# バイナリデータをファイルから読み込む
with io.open('example.bin', 'rb') as file:
    content = file.read()
    print(content)
    #出力:'Hello, World!'
```
 
3.バイト列をメモリ上で操作 (バッファ操作)
```python
import io

# バイナリデータのメモリバッファ
buffer = io.BytesIO(b'Hello, World!')

# メモリバッファから読み込む
content = buffer.read()
print(content)


# メモリバッファに書き込む
buffer.write(b' Python rocks!')
buffer.seek(0)  # バッファの先頭に戻す
print(buffer.read())
```
出力
```
b'Hello, World!'
b'Hello, World! Python rocks!'
```
 
4.テキストストリームの操作
```python
import io

# テキストデータをメモリ上で操作
buffer = io.StringIO('Hello, World!')

# メモリからデータを読み取る
content = buffer.read()
print(content)

# メモリにデータを書き込む
buffer.write(' Python is awesome!')
buffer.seek(0)  # バッファの先頭に戻す
print(buffer.read())
```
出力
```
Hello, World!
Hello, World! Python is awesome!
```

5.ファイルを行単位で読み書き
```python
import io

# ファイルに行を書き込む
with io.open('example.txt', 'w', encoding='utf-8') as file:
    file.writelines(['Hello, World!\n', 'Python is awesome!\n'])

# 行単位でファイルを読み込む
with io.open('example.txt', 'r', encoding='utf-8') as file:
    for line in file:
        print(line.strip())  # 行末の改行を削除
        #出力:Hello, World!
        #    Python is awesome!
```

<br><br>
- ### 11-3 `time` --- 時刻データの操作
`time` モジュールは、Pythonで時刻データを扱うための多くの機能を提供します。主に、システムの現在時刻の取得、時間のフォーマット、遅延処理などに使用されます。


#### 主な機能
- **`time.time()`**: 現在の時刻を、1970年1月1日00:00:00 UTC からの経過秒数（浮動小数点数）として取得します。
　　　　
- **`time.localtime([secs])`**: 指定した秒数（または現在時刻）をローカルタイムに変換します。戻り値は time.struct_time オブジェクトです。
　　　　
- **`time.gmtime([secs])`**: 指定した秒数（または現在時刻）をUTC（協定世界時）に変換します。戻り値は time.struct_time オブジェクトです。
 　　　　
- **`time.strftime(format[, t])`**: 指定したフォーマットで時刻を文字列として返します。time.localtime() や time.gmtime() を使って取得した struct_time オブジェクトを指定できます。
　　　　
- **`time.sleep(secs)`**: プログラムの実行を指定された秒数だけ一時停止します。遅延処理やスリープに使用されます。
　　　　
- **`time.perf_counter()`**:高精度なタイマーを返し、主にパフォーマンス計測に使用されます。返される値は実行時間を秒単位で表し、システムの起動時からの経過時間を測定します。
　　　　
- **`time.process_time()`**:プログラムのCPU処理時間を返します。CPU時間（実際にCPUが処理に使った時間）の測定に使います。

#### 利用例
1.現在時刻を取得
```python
import time

# 現在の時刻（エポックからの秒数）を取得
current_time = time.time()
print("エポックからの秒数:", current_time)

# 現在のローカル時刻を取得
local_time = time.localtime()
print("ローカル時刻:", local_time)

# 現在のUTC時刻を取得
utc_time = time.gmtime()
print("UTC時刻:", utc_time)
```
 出力例
```plaintext
エポックからの秒数: 1683249327.374758
ローカル時刻: time.struct_time(tm_year=2024, tm_mon=5, tm_mday=5, tm_hour=14, tm_min=8, tm_sec=47, tm_wday=6, tm_yday=126, tm_isdst=0)
UTC時刻: time.struct_time(tm_year=2024, tm_mon=5, tm_mday=5, tm_hour=5, tm_min=8, tm_sec=47, tm_wday=6, tm_yday=126, tm_isdst=0)
```
2.時刻のフォーマット
```python
import time

# ローカル時刻を取得
local_time = time.localtime()

# 時刻を指定したフォーマットで表示
formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
print("フォーマットされた時刻:", formatted_time)
```
 出力例
```plaintext
フォーマットされた時刻: 2024-05-05 14:08:47
```
3.経過時間の計測
```python
import time

# 計測開始時刻
start_time = time.perf_counter()

# 何かの処理（例: 2秒待機）
time.sleep(2)

# 計測終了時刻
end_time = time.perf_counter()

# 経過時間を計算
elapsed_time = end_time - start_time
print(f"経過時間: {elapsed_time:.4f}秒")
#出力:経過時間: 2.0002秒
```
 
4.日時の差分を計算
```python
import time

# 時刻の差分を計算する例
start_time = time.time()  # 現在のエポック時間を取得
time.sleep(3)             # 3秒間スリープ
end_time = time.time()    # スリープ後のエポック時間を取得

elapsed_time = end_time - start_time
print(f"経過時間: {elapsed_time}秒")
#出力:経過時間: 3.0001564025878906秒
```
 
<br><br>
- ### 11-4 `argparse` --- コマンドラインオプション解析
`argparse` は、コマンドライン引数を解析するためのモジュールです。コマンドラインからプログラムに引数を渡して、その引数に基づいた動作を実行する際に非常に便利です。

#### 主な機能
- **`argparse.ArgumentParser(description)`**: 
コマンドライン引数を解析するためのオブジェクトを作成します。このオブジェクトに引数を追加し、解析を行います。
　　　　
- **`argparse.ArgumentParser.add_argument('name', type=str, help="ユーザーの名前を指定")`**:
 コマンドライン引数を定義します。必須引数、オプション引数、デフォルト値、ヘルプメッセージなどを設定できます。
　　　　　　　　　
- **`argparse.ArgumentParser.parse_args()`**: 
定義した引数を解析し、結果を Namespace オブジェクトとして返します。引数は属性としてアクセス可能です。
　　　　
- **`argparse.ArgumentParser.print_help()`**: 
コマンドライン引数の使用方法を表示します（通常、-h または --help オプションで呼び出されます）。

#### 利用例

1.基本的な引数の解析
コマンドライン引数を解析して、その値を利用する簡単なプログラムを作成します。

```python
import argparse

# ArgumentParserオブジェクトを作成
parser = argparse.ArgumentParser(description="名前と年齢を受け取るプログラム")

# 引数を定義
parser.add_argument('name', type=str, help="名前を入力してください")
parser.add_argument('age', type=int, help="年齢を入力してください")

# 引数を解析
args = parser.parse_args()

# 引数を利用
print(f"名前: {args.name}")
print(f"年齢: {args.age}")
```
コマンドラインからの実行例
```bash
python script.py Alice 30
```
 出力例
```plaintext
名前: Alice
年齢: 30
```
2.オプション引数の使用
オプション引数（--verbose や --output など）を使って、プログラムの動作をカスタマイズできます。

```python
import argparse

# ArgumentParserオブジェクトを作成
parser = argparse.ArgumentParser(description="オプション引数の使用例")

# オプション引数を定義
parser.add_argument('--verbose', action='store_true', help="詳細モードを有効にする")
parser.add_argument('--output', type=str, help="出力ファイル名を指定")

# 引数を解析
args = parser.parse_args()

# オプション引数の処理
if args.verbose:
    print("詳細モードが有効です")

if args.output:
    print(f"出力先ファイル: {args.output}")
```
#### コマンドラインからの実行例
```bash
python script.py --verbose --output result.txt
```
 出力例
```plaintext
詳細モードが有効です
出力先ファイル: result.txt
```
3.デフォルト値を設定
引数にデフォルト値を指定することもできます。引数が指定されなかった場合、デフォルトの値が使用されます。

```python
import argparse

# ArgumentParserオブジェクトを作成
parser = argparse.ArgumentParser(description="デフォルト値の設定")

# 引数を定義（デフォルト値を設定）
parser.add_argument('--color', type=str, default="blue", help="色を指定")

# 引数を解析
args = parser.parse_args()

print(f"選択された色: {args.color}")
```
コマンドラインからの実行例
```bash
python script.py
```
出力例
```plaintext
選択された色: blue
```
引数が指定された場合：

```bash
python script.py --color red
```
 出力例
```plaintext
選択された色: red
```
4.ヘルプメッセージの自動生成
--help オプションを使って、プログラムの使い方を簡単に表示できます。

```bash
python script.py --help
```
 出力例
```plaintext
usage: script.py [-h] [--color COLOR]

デフォルト値の設定

optional arguments:
  -h, --help            show this help message and exit
  --color COLOR         色を指定
```
<br><br>
- ### 11-5 `logging` --- ログ記録機能
`logging` モジュールは、Pythonでログを記録することができます。ログを生成して、プログラムの動作を追跡したり、デバッグしたり、エラーメッセージを記録したりするのに非常に便利です。このモジュールは、ログメッセージの重要度に基づいて異なるレベルのログを記録することができ、さまざまなログの出力先（ファイル、コンソール、リモートサーバーなど）を設定することができます。

#### 主な機能
- **`logging.basicConfig(level, format, filename, filemode, datefmt)`**: 
ロギングの基本設定を行う。
　　　　
- **`logging.getLogger(name)`**: ロガーを取得する。
　　　　
- **`logging.debug(msg),logging.info(msg),logging.warning(msg), logging.error(msg), logging.critical(msg)`**: 指定されたレベルでログメッセージを記録する。
　　　　　　　　
- **`logging.StreamHandler()`**:ログメッセージをコンソールに出力するハンドラーを作成する。
　　　　
- **`logging.FileHandler(filename)`**:ログメッセージをファイルに出力するハンドラーを作成する。
　　　　　
- **`logging.Formatter(fmt)`**:ログメッセージのフォーマットを定義する。
#### 利用例
1. 基本的なログの記録

```python
import logging

# ログの設定
logging.basicConfig(level=logging.DEBUG)

# ログを記録
logging.debug('これはデバッグメッセージです')
logging.info('これは情報メッセージです')
logging.warning('これは警告メッセージです')
logging.error('これはエラーメッセージです')
logging.critical('これは重大なエラーメッセージです')
```
 出力例
```plaintext
`DEBUG:root`:これはデバッグメッセージです
`INFO:root`:これは情報メッセージです
`WARNING:root`:これは警告メッセージです
`ERROR:root`:これはエラーメッセージです
`CRITICAL:root`:これは重大なエラーメッセージです
```
2.ログのフォーマットをカスタマイズ
ログメッセージのフォーマットをカスタマイズすることができます。たとえば、タイムスタンプやログレベルを追加することができます。

```python
import logging

# フォーマットの設定
logging.basicConfig(level=logging.DEBUG, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# ログを記録
logging.debug('これはデバッグメッセージです')
logging.info('これは情報メッセージです')
```
 出力例
```plaintext
2024-12-03 10:00:00,000 - DEBUG - これはデバッグメッセージです
2024-12-03 10:00:00,001 - INFO - これは情報メッセージです
```
3.ログの出力先をファイルに変更
ログメッセージをコンソールではなくファイルに記録することもできます。

```python
import logging

# ファイルへのログ出力設定
logging.basicConfig(filename='app.log', level=logging.DEBUG, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# ログを記録
logging.debug('デバッグメッセージ')
logging.info('情報メッセージ')
```
 出力例 (app.log ファイル)
```plaintext
2024-12-03 10:00:00,000 - DEBUG - デバッグメッセージ
2024-12-03 10:00:00,001 - INFO - 情報メッセージ
```
4.ログのハンドラーを使って複数の出力先にログを記録
複数の出力先にログを記録するためには、ハンドラーを使います。たとえば、コンソールとファイル両方に出力することができます。

```python
import logging

# ロガーの作成
logger = logging.getLogger()

# ハンドラーを作成
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('app.log')

# フォーマットの設定
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

# ハンドラーの追加
logger.addHandler(console_handler)
logger.addHandler(file_handler)

# ログを記録
logger.debug('デバッグメッセージ')
logger.info('情報メッセージ')
```
 出力例 (コンソールと app.log に両方記録)
コンソール:

```plaintext
2024-12-03 10:00:00,000 - DEBUG - デバッグメッセージ
2024-12-03 10:00:00,001 - INFO - 情報メッセージ
```
app.log ファイル:

```plaintext
2024-12-03 10:00:00,000 - DEBUG - デバッグメッセージ
2024-12-03 10:00:00,001 - INFO - 情報メッセージ
```
<br><br>
- ### 11-6 `getpass` --- パスワード入力
`getpass` モジュールは、ユーザーがパスワードを入力する際に入力内容を表示せずに取得できる機能を提供します。これにより、ターミナルでパスワードを入力しても、セキュリティ上、画面に表示されることがなくなります。このモジュールは、ユーザーが入力する情報を秘匿するために使用されます。

#### 主な機能
- **`getpass.getpass(prompt)`**: 
ユーザーにパスワードを入力させ、その内容をターミナルに表示せずに取得します。
　　　　
- **`getpass.getuser()`**: パスワード入力を促すメッセージをカスタマイズできます。
　　　　
- **`例外処理 (EOFError と KeyboardInterrupt)`**: 入力がキャンセルされた場合や、他のエラーが発生した場合に例外を処理できます。
#### 利用例
1. 基本的なパスワード入力

```python
import getpass

# パスワードを入力
password = getpass.getpass("Enter your password: ")

# 入力されたパスワードを表示（例として）
print(f"You entered: {password}")
```
 出力例
```plaintext
Enter your password: ********
You entered: mysecretpassword
※ 実際には、パスワード入力時に入力内容は表示されません（******** は表示例です）。
```

2.パスワードの確認
ユーザーが2回パスワードを入力し、それらが一致するか確認する例です。

```python
import getpass

# パスワードの入力
password1 = getpass.getpass("Enter your password: ")
password2 = getpass.getpass("Confirm your password: ")

# パスワードが一致するか確認
if password1 == password2:
    print("Passwords match!")
else:
    print("Passwords do not match.")
```
 出力例
```plaintext
Enter your password: ********
Confirm your password: ********
Passwords match!
```
3.例外処理の利用
getpass では、EOFError や KeyboardInterrupt などのエラーが発生した場合、適切に処理できます。

```python
import getpass

try:
    # パスワード入力
    password = getpass.getpass("Enter your password: ")
    print("Password entered successfully.")
except (EOFError, KeyboardInterrupt):
    print("\nInput cancelled.")
```
 出力例（ユーザーが入力をキャンセルした場合）
```plaintext
Enter your password: 
Input cancelled.
```
<br><br>
- ### 11-7 `platform` --- 実行プラットフォーム情報
`platform` モジュールは、現在の実行環境（プラットフォーム）の情報を取得するための機能を提供します。このモジュールを使用すると、OSの種類やバージョン、システムのアーキテクチャなど、実行環境に関するさまざまな情報を取得できます。

#### 主な機能

- **`platform.system(), platform.version(), platform.architecture()`**: 
-使用中のオペレーティングシステムの名前、バージョン、アーキテクチャなどを取得できます。
　　　　
- **`platform.python_version()`**: Pythonインタプリタやそのバージョンに関する情報を提供します。
　　　　　
- **`platform.mac_ver()`**: 
Mac、Windows、Linuxなど、プラットフォームごとに異なる詳細な情報を得ることができます。
#### 利用例
1. OS名とバージョンを取得
```python
import platform

# OSの名前を取得
os_name = platform.system()

# OSのバージョンを取得
os_version = platform.version()

# OSアーキテクチャを取得
architecture = platform.architecture()

print(f"OS: {os_name}")
print(f"Version: {os_version}")
print(f"Architecture: {architecture}")
```
出力例
```plaintext
OS: Windows
Version: 10.0.19041
Architecture: ('64bit', 'WindowsPE')
```
2.プラットフォーム情報を取得
platformモジュールの`platform()`関数を使うと、より詳細なプラットフォームの情報を一度に取得できます。

```python
import platform

# プラットフォーム情報を取得
platform_info = platform.platform()

print(f"Platform info: {platform_info}")
#出力:Platform info: Windows-10-10.0.19041-SP0
```
 
3.Pythonの実行環境を取得
実行中のPythonのバージョンやビット数、実行環境の詳細情報を取得できます。

```python
import platform

# Pythonのバージョンを取得
python_version = platform.python_version()

# Pythonのビット数を取得
python_arch = platform.architecture()

print(f"Python version: {python_version}")
print(f"Python architecture: {python_arch}")
```
 出力例
```plaintext
Python version: 3.8.5
Python architecture: ('64bit', 'ELF')
```
4.カスタムプロンプトを使って詳細情報を取得
`platform` モジュールには、特定のプラットフォームに関する詳細な情報を得るための専用関数がいくつかあります。たとえば、mac_ver()（MacOSのバージョン情報）やlinux_distribution()（Linuxのディストリビューション情報）などです。

```python
import platform

# MacOSのバージョン情報を取得
mac_version = platform.mac_ver()

# Linuxのディストリビューション情報を取得
linux_dist = platform.linux_distribution()

print(f"Mac Version: {mac_version}")
print(f"Linux Distribution: {linux_dist}")
```
 出力例（Macの場合）
```plaintext
Mac Version: ('10.15.6', ('', '', ''), 'x86_64')
Linux Distribution: ('Ubuntu', '20.04', 'focal')
```

## 12. 並行実行
- ### 12-1 `threading` --- スレッド並列処理
`threading` モジュールは、Pythonにおける並列処理をサポートするためのモジュールです。スレッドを使用して、複数の処理を同時に実行することができます。スレッドは、特にI/Oバウンドなタスク（例えば、ファイル操作やネットワーク通信）を並列で実行する場合に有効です。

#### 主な機能
- **`threading.Thread(target, name, args, kwargs, daemon)`**: 
threading.Thread クラスを使って新しいスレッドを作成し、実行することができます。
　　　　
- **`threading.Lock()`**: 単に新しいロックオブジェクトを作成するためのものです。
　　　　
- **`thread.join(timeout=None)`**:
 `join()` メソッドを使って、スレッドが終了するまで待つことができます。
　　　　
- **`thread.daemon()`**: 
デーモンスレッドを使用することで、メインスレッドの終了とともにスレッドを自動的に終了させることができます。
#### 利用例
1. シンプルなスレッドの作成
```python
import threading
import time

# スレッドで実行する関数
def greet():
    time.sleep(2)
    print("Hello from the thread!")

# スレッドを作成
thread = threading.Thread(target=greet)

# スレッドを開始
thread.start()

# メインスレッドが終了する前にスレッドの終了を待つ
thread.join()

print("Thread has finished execution")
#出力:Hello from the thread!
#     Thread has finished execution
```
 

この例では、スレッドを使って数値を1秒ごとに印刷しています。`thread.join()` によって、メインスレッドはサブスレッドが終了するまで待機します。

2.複数のスレッドを使った並列処理
```python
import threading
import time

# スレッドで実行する関数
def print_numbers(thread_name):
    for i in range(5):
        time.sleep(1)
        print(f"Thread {thread_name}: {i}")

# 複数のスレッドを作成
threads = []
for i in range(3):
    thread = threading.Thread(target=print_numbers, args=(i,))
    threads.append(thread)
    thread.start()

# メインスレッドが終了する前にすべてのスレッドの終了を待つ
for thread in threads:
    thread.join()

print("All threads have finished execution")
#出力:Thread 0 has finished!
#    Thread 1 has finished!
#    All threads have finished execution
```

ここでは、3つのスレッドが並行して実行され、各スレッドが数値を1秒ごとに出力します。スレッドが終了するまでメインスレッドは待機します。

3.スレッド間で共有するリソースをロックで保護
スレッド間でリソース（例えば、変数）を共有する場合、リソースの競合を防ぐために Lock を使用します。

```python
import threading

# ロックを作成
lock = threading.Lock()
counter = 0

# スレッドで実行する関数
def increment_counter():
    global counter
    with lock:
        for _ in range(100000):
            counter += 1

# 複数のスレッドを作成
threads = []
for _ in range(2):
    thread = threading.Thread(target=increment_counter)
    threads.append(thread)
    thread.start()

# メインスレッドが終了する前にすべてのスレッドの終了を待つ
for thread in threads:
    thread.join()

print(f"Counter value: {counter}")
#出力:Counter value: 200000
```
 
この例では、2つのスレッドが counter をインクリメントします。lock を使用して、スレッド間での競合状態を防ぎます。
<br><br>
- ### 12-2 `multiprocessing` --- プロセス並列処理
`multiprocessing` モジュールは、Pythonでプロセス並列処理を行うためのツールです。スレッドではなく独立したプロセスを使用するため、複数のCPUコアを有効に活用でき、特にCPUバウンドなタスクに対して効果的です。これにより、並列処理によるパフォーマンス向上を実現できます。

#### 主な機能
- **`multiprocessing.Process(target=function, args=(arg1, arg2), kwargs={key: value})`**:  
クラスを使用して新しいプロセスを作成し、実行することができます。
　　　　
- **`multiprocessing.Value(typecode, value=0)`**: 
Value や Array を使用して、プロセス間でデータを共有できます。

#### 利用例
1. シンプルなプロセスの作成
```python
import multiprocessing
import time

# プロセスで実行する関数
def simple_task():
    time.sleep(1)
    print("Task completed")

# プロセスを作成
process = multiprocessing.Process(target=simple_task)

# プロセスを開始
process.start()

# プロセスの終了を待つ
process.join()

print("Process has finished execution")
#出力:Task completed
#     Process has finished execution

```
 
この例では、新しいプロセスを作成して、数値を1秒ごとに出力しています。`process.join()` でメインプロセスが終了する前に、サブプロセスが完了するのを待機します。

2.複数のプロセスを使った並列処理
```python
import multiprocessing
import time

# プロセスで実行する関数
def print_numbers(thread_name):
    for i in range(5):
        time.sleep(1)
        print(f"Process {thread_name}: {i}")

# 複数のプロセスを作成
processes = []
for i in range(3):
    process = multiprocessing.Process(target=print_numbers, args=(i,))
    processes.append(process)
    process.start()

# メインプロセスが終了する前にすべてのプロセスの終了を待つ
for process in processes:
    process.join()

print("All processes have finished execution")
```
 出力例
```plaintext
Process 0: 0
Process 1: 0
Process 2: 0
Process 0: 1
Process 1: 1
Process 2: 1
Process 0: 2
Process 1: 2
Process 2: 2
Process 0: 3
Process 1: 3
Process 2: 3
Process 0: 4
Process 1: 4
Process 2: 4
All processes have finished execution
```
ここでは、3つのプロセスを使って並列に処理を行い、それぞれが1秒ごとに数値を出力しています。プロセスが終了するのをメインプロセスが待機します。

3.プロセス間でのデータ共有
プロセス間でデータを共有するには、Value や Array を使用します。

```python
import multiprocessing

# プロセスで実行する関数
def increment_counter(counter):
    for _ in range(100000):
        counter.value += 1

# Valueオブジェクトを作成
counter = multiprocessing.Value('i', 0)

# プロセスを作成
processes = []
for _ in range(2):
    process = multiprocessing.Process(target=increment_counter, args=(counter,))
    processes.append(process)
    process.start()

# メインプロセスが終了する前にすべてのプロセスの終了を待つ
for process in processes:
    process.join()

print(f"Counter value: {counter.value}")
#出力:Counter value: 101354
```

この例では、2つのプロセスが counter という共有変数をインクリメントします。counter は Value を使って共有され、プロセス間でデータの競合が防止されています。

4.プールを使った並列処理
Pool を使用することで、複数のプロセスを管理し、タスクを並列に実行することができます。

```python
import multiprocessing

# 各プロセスで実行する関数
def square(n):
    return n * n

# プールを作成し、並列処理を実行
with multiprocessing.Pool(processes=4) as pool:
    result = pool.map(square, [1, 2, 3, 4, 5])

print(result)
#出力:[1, 4, 9, 16, 25]
```
 
この例では、Pool を使ってリスト内の数字を並列に処理し、各数字の平方を計算しています。

<br><br>
- ### 12-3 `concurrent.futures` --- 並列タスク実行
`concurrent.futures` モジュールは、並列処理を簡単に実行できる高レベルなインターフェースを提供します。主に ThreadPoolExecutor と ProcessPoolExecutor という2つのクラスがあり、スレッドやプロセスを使って非同期にタスクを実行できます。これにより、複雑な並列処理をシンプルに扱うことができます。

#### 主な機能
- **`ThreadPoolExecutor(max_workers=None)`**: スレッドを使用してタスクを並列に実行します。スレッドプールを使用することで、スレッド管理のオーバーヘッドを減らし、効率的にタスクを並列実行できます。
　　　　
- **`ProcessPoolExecutor(max_workers=None)`**: プロセスを使用してタスクを並列に実行します。これは、CPUバウンドのタスク（計算が重いタスク）に特に有用です。プロセス間はメモリを共有しないため、スレッドプールとは異なり、multiprocessing の機能を活用しています。

#### 利用例
1. スレッドプールを使った並列タスク実行
```python
import concurrent.futures
import time

# タスクを実行する関数
def task(n):
    time.sleep(1)
    return f"Task {n} completed"

# ThreadPoolExecutorを使って並列タスクを実行
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
    # submit()を使ってタスクを非同期に実行
    futures = [executor.submit(task, i) for i in range(5)]
    
    # 結果を取得
    for future in concurrent.futures.as_completed(futures):
        print(future.result())
```
 出力例
```plaintext
Task 0 completed
Task 1 completed
Task 2 completed
Task 3 completed
Task 4 completed
```
この例では、ThreadPoolExecutor を使って5つのタスクを非同期に並列実行し、順次その結果を出力しています。max_workers=3 により同時に実行できるスレッド数を3に制限しています。

2.プロセスプールを使った並列タスク実行
```python
import concurrent.futures

# CPUバウンドなタスク
def compute_square(n):
    return n * n

# ProcessPoolExecutorを使って並列タスクを実行
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
    # map()を使ってタスクを非同期に実行
    results = executor.map(compute_square, [1, 2, 3, 4, 5])
    
    # 結果を表示
    for result in results:
        print(result)
```
 出力例
```plaintext
1
4
9
16
25
```
この例では、ProcessPoolExecutor を使用して、5つの数の平方を並列に計算しています。`map()` を使うと、結果がリストとしてまとめて返されます。

3.`submit()` と `result()`を使った非同期処理
```python
import concurrent.futures

# タスクを実行する関数
def multiply(x, y):
    return x * y

# ThreadPoolExecutorを使って非同期タスクを実行
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    # submit() で非同期タスクを送信
    future1 = executor.submit(multiply, 2, 3)
    future2 = executor.submit(multiply, 4, 5)
    
    # 結果を取得
    print(future1.result())  # 6
    print(future2.result())  # 20
```
 
`submit()` を使うと、非同期タスクを送信できます。future.result() を呼び出すことで、タスクが完了するまでブロックされ、結果が得られます。

4.エラーハンドリング
```python
import concurrent.futures

# エラーを発生させるタスク
def divide(x, y):
    return x / y

# ThreadPoolExecutorを使って並列タスクを実行
with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = [executor.submit(divide, 10, 2), executor.submit(divide, 10, 0)]
    
    for future in concurrent.futures.as_completed(futures):
        try:
            print(future.result())
        except ZeroDivisionError as e:
            print(f"Error: {e}")
```
 出力例
```plaintext
5.0
Error: division by zero
```
`submit()` と `result()` を使うことで、タスク内で発生したエラーも適切にキャッチできます。`as_completed()` を使うと、タスクが完了した順に結果を処理できます。

<br><br>
- ### 12-4 `subprocess` --- サブプロセス管理
`subprocess`モジュールは、外部のプログラムやコマンドを実行するために使用されます。Pythonプログラムから他のプログラムを呼び出す際に非常に便利で、システムのコマンドや外部ツールをPython内で制御できます。これにより、Pythonスクリプト内でシェルコマンドや他の実行可能なプログラムを簡単に実行したり、結果を取得したりすることができます。

#### 主な機能

- **`subprocess.run(args)`**: コマンドを実行してその結果を取得するシンプルな方法です。
  　　　　  
- **`subprocess.Popen(args)`**: 
より細かい制御を行いたい場合に使用します。標準入力・出力の処理や非同期処理を行えます。

#### 利用例
 `subprocess.run()` を使ったシンプルなコマンド実行
```python
import subprocess

# 'echo' コマンドを実行
result = subprocess.run(['echo', 'Hello, World!'], capture_output=True, text=True)

# 標準出力を表示
print(result.stdout)  # 出力: Hello, World!
```
 エラー処理と結果の確認
```python
import subprocess

try:
    # 存在しないコマンドを実行
    result = subprocess.run(['nonexistent_command'], capture_output=True, text=True, check=True)
except FileNotFoundError as e:
    print(f"FileNotFoundError: {e}")
except subprocess.CalledProcessError as e:
    print(f"Error occurred: {e}")
    print(f"Standard output: {e.stdout}")
    print(f"Standard error: {e.stderr}")
    # 出力: FileNotFoundError: [Errno 2] No such file or directory: 'nonexistent_command'
```
 標準出力と標準エラー出力のキャプチャ
```python
import subprocess

# 'ls' コマンドを実行
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)

# 標準出力を表示
print(result.stdout)

# 標準エラー出力を表示
if result.stderr:
    print(result.stderr)
# 出力: 
#total 48
#drwxr-xr-x  5 user user 4096 Dec 19 15:30 directory1
#-rw-r--r--  1 user user    0 Dec 19 15:30 file1.txt
#-rw-r--r--  1 user user    0 Dec 19 15:30 file2.txt
#-rw-r--r--  1 user user    0 Dec 19 15:30 file3.txt
```
 `subprocess.Popen()` を使った非同期プロセスの管理
```python
import subprocess

# 'sleep' コマンドを非同期に実行
process = subprocess.Popen(['sleep', '5'])

# プロセスが終了するのを待つ
process.wait()

print("Process finished.")
#出力: Process finished.
```
 標準入力をリダイレクトしてコマンド実行
```python
import subprocess

# 'grep' コマンドに入力をリダイレクト
process = subprocess.Popen(['grep', 'foo'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)

# 入力を送信して結果を取得
stdout, stderr = process.communicate(input='foo\nbar\nfoo\n')

# 結果を表示
print(stdout)  # 出力: foo\nfoo
```
 タイムアウトを設定してコマンドを実行
```python
import subprocess

try:
    # タイムアウトを設定してコマンドを実行
    result = subprocess.run(['sleep', '10'], capture_output=True, text=True, timeout=5)
except subprocess.TimeoutExpired as e:
    print(f"Command timed out: {e}")
    #出力:Command timed out: Command '['sleep', '10']' timed out after 5 seconds
```


<br><br>
- ### 12-5 `sched` --- イベントスケジューラー
`Sched` モジュールは、Python において時間に基づいてタスクをスケジュールするための便利なツールを提供します。指定した時間または遅延後に特定の関数を実行することができます。また、繰り返しタスクの実行や優先順位に基づくタスク管理なども可能です。

#### 主な機能
- **`sched.scheduler(time.time, time.sleep)`**: スケジューラオブジェクトを作成します。
　　　　
- **`scheduler.enter(delay, priority, action)`**: 指定した遅延後にイベントをスケジュールします。
　　　　
- **`scheduler.run()`**: スケジューラを実行し、イベントを処理します。
　　　　　
- **`scheduler.cancel(event)`**: スケジュールされたイベントをキャンセルします。

#### 利用例
 単一のイベントをスケジュールする
```python
import sched
import time

# スケジューラのインスタンスを作成
scheduler = sched.scheduler(time.time, time.sleep)

# 実行する関数を定義
def print_event(message):
    print(message)

# 2秒後に print_event を実行するイベントをスケジュール
scheduler.enter(2, 1, print_event, ('Hello, World!',))

# スケジューラを実行
scheduler.run()
```
 出力
```
Hello, World
```
 定期的に実行されるタスクのスケジュール
```python
import sched
import time

# スケジューラのインスタンスを作成
scheduler = sched.scheduler(time.time, time.sleep)

# 実行する関数を定義
def print_message():
    print("Repeating Task")
    # 次のタスクをスケジュール（5秒ごと）
    scheduler.enter(5, 1, print_message, ())

# 最初のタスクをスケジュール
scheduler.enter(5, 1, print_message, ())

# スケジューラを実行
scheduler.run()
```
 出力 (5秒ごとに実行):
```arduino
Repeating Task
Repeating Task
Repeating Task
...
```
 イベントに優先度を設定
```python
import sched
import time

# スケジューラのインスタンスを作成
scheduler = sched.scheduler(time.time, time.sleep)

# 実行する関数を定義
def task_1():
    print("Task 1 executed")

def task_2():
    print("Task 2 executed")

# 優先度を設定してイベントをスケジュール
scheduler.enter(2, 1, task_1, ())  # 優先度1、引数は空のタプル
scheduler.enter(2, 2, task_2, ())  # 優先度2、引数は空のタプル

# スケジューラを実行
scheduler.run()
```
出力

```arduino
Task 1 executed
Task 2 executed
```

<br><br>
- ### 12-6 `queue` --- 同期キュークラス
`queue` モジュールは、スレッド間でデータを安全にやり取りするための同期キューを提供します。これにより、複数のスレッドが同時にデータを扱う場合でも、データの整合性が保たれます。特に、マルチスレッドアプリケーションで使われることが多いです。

#### 主な機能
- **`queue.Queue`**: 
最も基本的なキューで、FIFO（First In, First Out）順にデータを処理します。キューが空のときにデータを取得しようとした場合、スレッドはブロックされます。
　　　　
- **`queue.LifoQueue`**:
LIFO（Last In, First Out）順にデータを処理します。最後に入れたデータが最初に出てきます。
　　　　
- **`queue.PriorityQueue`**:
優先度付きキューで、優先度の高いアイテムが最初に処理されます。アイテムは (priority, data) の形式で格納されます。

主なメソッド・関数
- **`put(item, block=True, timeout=None)`**:
 アイテムをキューに追加します。block が True の場合、キューが満杯のときにブロックされます。timeout でブロックの最大時間を指定できます。
　　　　
- **`get(block=True, timeout=None)`**: キューからアイテムを取り出します。キューが空の場合、block が True のときにブロックされます。timeout で最大待機時間を指定できます。
　　　　
- **`empty()`**: キューが空かどうかを確認します。
　　　　
- **`full()`**: キューが満杯かどうかを確認します。
　　　　
- **`qsize()`**: キューに格納されているアイテムの数を取得します（スレッドセーフではないため注意が必要）。
#### 利用例
queue.Queue を使った基本的なキュー操作
```python
import queue

# キューを作成
q = queue.Queue()

# アイテムをキューに追加
q.put(10)
q.put(20)

# アイテムを取り出す
item1 = q.get()  # 10
item2 = q.get()  # 20

print(item1, item2)  # 出力: 10 20
```
queue.LifoQueue を使った LIFO キュー操作
```python
import queue

# LIFO キューを作成
q = queue.LifoQueue()

# アイテムをキューに追加
q.put(10)
q.put(20)

# アイテムを取り出す（逆順で取り出される）
item1 = q.get()  # 20
item2 = q.get()  # 10

print(item1, item2)  # 出力: 20 10
```
queue.PriorityQueue を使った優先度付きキュー操作
```python
import queue

# 優先度付きキューを作成
pq = queue.PriorityQueue()

# アイテムを優先度とともに追加 (優先度, データ)
pq.put((2, "low priority task"))
pq.put((1, "high priority task"))

# アイテムを取り出す（優先度が高いものが先に処理される）
priority, task = pq.get()  # ('high priority task')
print(task)  # 出力: high priority task

priority, task = pq.get()  # ('low priority task')
print(task)  # 出力: low priority task
```
## 13. ネットワーク通信とプロセス間通信
- ### 13-1 `asyncio` --- 非同期I/O

`asyncio` は、非同期 I/O を扱うためのツールです。これにより、時間のかかる I/O 処理を効率的に並行して実行でき、アプリケーションのパフォーマンスを向上させます。

#### 主な機能
- **`asyncio.run(main())`**: 
同期プログラムを実行するためのエントリーポイントです。main() は非同期関数（コルーチン）である必要があります。asyncio.run() は、イベントループを起動し、指定されたコルーチンを実行します。
　　　　
- **`asyncio.create_task(coro)`**: 
新しい非同期タスクを作成して、バックグラウンドで実行します。coro という非同期関数（コルーチン）をタスクにして実行します。イベントループによって処理されます。
　　　　
- **` syncio.gather(*coros)`**:
 複数の非同期タスクを並行して実行し、その結果を待機します。｀`asyncio.gather()` は渡されたコルーチンを並列に実行し、すべてのコルーチンが完了するまで待機します。 他のタスクが完了するのを待つ。
#### 利用例
```python
import asyncio

async def main():
    print("Hello, asyncio!")  # メッセージを表示
    await asyncio.sleep(1)  # 1秒間非同期で待機（CPUを使わず他の処理ができる）
    print("Asyncio finished")  # 非同期処理終了後に表示

# asyncio.run() は非同期プログラムを実行するために必須
asyncio.run(main())  # main() は必須の非同期関数
#出力:Hello, asyncio!
#    Asyncio finished
```


- ### 13-2 `socket` --- ネットワークインターフェース
Python の `socket` モジュールは、ネットワーク通信を行うためのインターフェースを提供します。このモジュールを使うことで、クライアントとサーバ間の通信、データ送受信、ソケットの管理などを行うことができます。
#### 主な機能 

- **`socket.socket(family, type)`**: 新しいソケットを作成。
　　　　
- **`socket.bind(address)`**: ソケットを特定のアドレスにバインド（関連付け）。
　　　　
- **`socket.listen(backlog)`**: サーバが接続を待機するためのリスニング状態にする。

#### 利用例

サーバがクライアントからの接続を待機し、接続があったらデータを受け取る例です。

```python
import socket

# ソケットの作成
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# アドレスとポート番号にバインド
server_socket.bind(('localhost', 8080))

# 接続待機状態にする
server_socket.listen(1)

print("接続待機中...")

# 接続を受け入れ
client_socket, client_address = server_socket.accept()
print(f"接続されたクライアント: {client_address}")

# データを受け取る
data = client_socket.recv(1024)
print(f"受け取ったデータ: {data.decode()}")

# 接続を閉じる
client_socket.close()
server_socket.close()
```

クライアントがサーバに接続し、データを送信する例です。

```python
import socket

# ソケットの作成
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# サーバに接続
client_socket.connect(('localhost', 8080))

# データを送信
client_socket.sendall(b'Hello, Server!')

# 接続を閉じる
client_socket.close()
```
<br><br>
- ### 13-3 `ssl` --- ソケットのTLS/SSLラッパー
`ssl` モジュールは、ソケット通信に対して TLS（Transport Layer Security）や SSL（Secure Sockets Layer）を使用した暗号化を提供するツールです。これにより、インターネット上でのデータ通信を安全に暗号化し、第三者による盗聴や改竄を防ぐことができます。

#### 主な機能
- **`ssl.wrap_socket(sock)`**: 既存のソケットを SSL/TLS ソケットにラップする関数。
　　　　
- **`ssl.create_default_context()`**:
 SSL/TLS 通信の設定を簡単に構築するためのコンテキストを作成する関数。
　　　　
- **`SSLContext(protocol)`**: 
TLS/SSL 設定を管理するクラス。証明書の設定、暗号化アルゴリズムの指定、クライアント認証の管理などができます。
#### 利用例

サーバ側 (SSL/TLS サーバの設定)
```python
import socket
import ssl

# ソケットの作成
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# アドレスとポート番号にバインド
server_socket.bind(('localhost', 8080))

# 接続待機状態にする
server_socket.listen(1)

# SSL コンテキストの作成
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile='server.crt', keyfile='server.key')

print("SSL/TLS サーバを待機中...")

# 接続を受け入れる（SSL/TLSでラップ）
client_socket, client_address = server_socket.accept()
ssl_client_socket = context.wrap_socket(client_socket, server_side=True)

print(f"SSL/TLS 接続されたクライアント: {client_address}")

# データの受信
data = ssl_client_socket.recv(1024)
print(f"受け取ったデータ: {data.decode()}")

# 接続を閉じる
ssl_client_socket.close()
server_socket.close()
```
クライアント側 (SSL/TLS クライアントの設定)
```python
import socket
import ssl

# ソケットの作成
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# SSL/TLS コンテキストの作成
context = ssl.create_default_context()

# サーバに接続（SSL/TLSでラップ）
ssl_client_socket = context.wrap_socket(client_socket, server_hostname='localhost')
ssl_client_socket.connect(('localhost', 8080))

# データの送信
ssl_client_socket.sendall(b'Hello, SSL/TLS Server!')

# 接続を閉じる
ssl_client_socket.close()
```
重要な設定
`create_default_context()`: セキュリティを強化するために、デフォルトで証明書の検証、TLSv1.2以上を使用する設定になっています。
`wrap_socket()`: 既存のソケットを SSL/TLS にラップするための関数。`context.wrap_socket()` とも同様の役割を持ちますが、SSLContext を利用する方がより柔軟で強力です。

## 14. インターネットデータ操作
- ### 14-1 `email` --- 電子メールとMIME処理
`email` モジュールは、電子メールの作成、解析、送信をシンプルに行うための便利な機能を提供します。このモジュールは、特に MIME（Multipurpose Internet Mail Extensions）形式に対応しており、テキスト、HTML メール、添付ファイルなど、さまざまなコンテンツを簡単に扱うことができます。

#### 主な機能
- **`EmailMessage()`**: メールの本文、ヘッダー、添付ファイルを管理するクラス。
　　　　
- **`MIMEText(text)`**: テキスト形式のメール本文を作成するクラス。
　　　　
- **`MIMEMultipart()`**: 
複数部分（テキスト、HTML、添付ファイルなど）を持つメールを作成するクラス。
　　　　
- **`MIMEBase(_maintype, _subtype)`**: 
任意のバイナリデータ（添付ファイルなど）をメールに追加するための基底クラス。
　　　　
- **`BytesParser()`**: バイナリ形式のメールメッセージを解析するためのクラス。
#### 利用例
`email` モジュールを使って、テキストと HTML の両方の本文を持つメールを作成し、添付ファイルを加える方法です。

```python
import smtplib
from email.message import EmailMessage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# メールの作成
msg = MIMEMultipart()
msg['From'] = 'sender@example.com'
msg['To'] = 'receiver@example.com'
msg['Subject'] = 'テストメール'

# メールのテキスト部分
text_part = MIMEText('これはテキスト形式の本文です。', 'plain')
msg.attach(text_part)

# メールのHTML部分
html_part = MIMEText('<html><body><h1>HTMLメール</h1><p>これはHTML形式の本文です。</p></body></html>', 'html')
msg.attach(html_part)

# 添付ファイルの追加
filename = 'example.txt'
attachment = open(filename, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={filename}')
msg.attach(part)

# SMTP サーバーに接続してメールを送信
with smtplib.SMTP('smtp.example.com') as server:
    server.login('sender@example.com', 'password')
    server.sendmail(msg['From'], msg['To'], msg.as_string())

print('メールが送信されました')
```
<br><br>
- ### 14-2 `json` --- JSONエンコード/デコード
`json` モジュールは、JSON（JavaScript Object Notation）形式でデータをエンコード（シリアライズ）およびデコード（デシリアライズ）するための機能を提供します。Python のオブジェクトを JSON 形式で保存・送信したり、JSON 形式のデータを Python のオブジェクトとして扱うことができます。

#### 主な機能

- **`json.dumps(obj)`**: Python オブジェクトを JSON 形式の文字列に変換する。
　　　　
- **`json.loads(str)`**: JSON 形式の文字列を Python オブジェクトに変換する。
　　　　
- **`json.dump(obj, fp)`**: Python オブジェクトを JSON 形式でファイルに書き込む。
　　　　
- **`json.dumps(obj)`**: JSON 形式の文字列に変換（シリアライズ）するために使用します。
#### 利用例
`json.dumps()` を使用して、Python の辞書を `JSON` 形式にエンコードし、`json.loads()` を使って `JSON` 文字列を Python の辞書にデコードする例です。

```python
import json

# Python オブジェクト（辞書）の作成
data = {"name": "Alice", "age": 25, "city": "Wonderland"}

# Python オブジェクトを JSON 形式の文字列にエンコード
json_string = json.dumps(data)
print(json_string)

# JSON 文字列を Python オブジェクトにデコード
decoded_data = json.loads(json_string)
print(decoded_data)
# {"name": "Alice", "age": 25, "city": "Wonderland"}
# {'name': 'Alice', 'age': 25, 'city': 'Wonderland'}
```
<br><br>
- ### 14-3 `mailbox` --- メールボックス操作
`mailbox` モジュールは、メールボックス（電子メールを格納するファイル形式）を操作するためのツールを提供します。このモジュールを使うと、`mbox` や `Maildir` 形式のメールボックス内のメールの読み書きや管理を簡単に行うことができます。

#### 主な機能
- **`mailbox.mbox(file)`**: 
mbox 形式のメールボックスを操作するためのクラス。複数のメールを一つのファイルに格納します。
　　　　
- **`mailbox.Maildir(directory)`**: Maildir 形式のメールボックスを操作するためのクラス。メールが個別のファイルとして格納される形式です。
　　　　
- **`mailbox.PortableUnixMailbox(file)`**: 
MIME メールを解析するためのクラス。異なる形式のメールを扱うことができます。
#### 利用例
mailbox.mbox を使用して、mbox 形式のメールボックスを操作し、新しいメールを追加したり、保存されたメールを読み取る方法を紹介します。

```python
import mailbox

# mbox ファイルを開く
mbox = mailbox.mbox('example.mbox')

# メールを追加
new_message = mailbox.Message()
new_message.set_payload('This is a new message')
new_message['From'] = 'sender@example.com'
new_message['To'] = 'receiver@example.com'
new_message['Subject'] = 'Test Message'

mbox.add(new_message)

# メールの読み込み
for message in mbox:
    print(f"From: {message['From']}")
    print(f"Subject: {message['Subject']}")
    print(f"Body: {message.get_payload()}")
    print("-" * 40)

# メールボックスを保存
mbox.flush()
```

<br><br>
- ### 14-4 `mimetypes` --- MIMEタイプとファイル名のマッピング
`mimetypes` モジュールは、ファイル名や拡張子から `MIME タイプ`（インターネットメディアタイプ）を推測するためのツールを提供します。このモジュールを使用することで、ファイルの拡張子に基づいてその `MIME` タイプを取得したり、逆に `MIME` タイプから適切な拡張子を推測することができます。

#### 主な機能
- **`mimetypes.guess_type(url)`**: 
ファイル名または URL を渡すと、対応する MIME タイプとエンコーディングを推測します。
　　　　
- **`mimetypes.guess_all_extensions(type)`**: 
MIME タイプから対応するすべての拡張子をリストで返します。
　　　　
- **`mimetypes.init()`**: 
MIME タイプと拡張子のマッピングを初期化します（通常は自動的に行われます）。
#### 利用例
`mimetypes.guess_type()` を使用して、ファイル名から MIME タイプを推測する方法を示します。

```python
import mimetypes

# ファイル名に基づいて MIME タイプを推測
mime_type, encoding = mimetypes.guess_type('example.html')
print(f"MIME Type: {mime_type}")
print(f"Encoding: {encoding}")

# ファイル名が存在しない場合（拡張子が不明な場合）
mime_type, encoding = mimetypes.guess_type('example.xyz')
print(f"MIME Type: {mime_type}")
print(f"Encoding: {encoding}")
```

出力
```
MIME Type: text/html
Encoding: None
MIME Type: chemical/x-xyz
Encoding: None
```
このコードでは、`example.html` というファイル名から `MIME` タイプを推測し、`.xyz `のような拡張子が不明な場合には `None` が返されます。


<br><br>
- ### 14-5 `base64` --- Base16, Base32, Base64データのエンコード
`base64` モジュールは、Base16（Hex）、Base32、Base64 などのエンコード・デコードを行うためのツールを提供します。これにより、バイナリデータをテキスト形式に変換したり、逆にテキスト形式からバイナリデータを取得することができます。

#### 主な機能
- **`base64.b64encode(bytes)`**: バイナリデータを Base64 エンコードします。
　　　　
- **`base64.b64decode(bytes or str)`**: 
Base64 エンコードされたデータをデコードします。
　　　　
- **`base64.b16encode(bytes)`**: バイナリデータを Base16（Hex）エンコードします。
　　　　
- **`base64.b16decode(bytes or str)`**: 
Base16 エンコードされたデータをデコードします。
　　　　
- **`base64.b32encode(bytes)`**: バイナリデータを Base32 エンコードします。
　　　　
- **`base64.b32decode(bytes or str)`**: 
Base32 エンコードされたデータをデコードします。
#### 利用例
以下は、バイナリデータを Base64 エンコードし、その後デコードする例です。

```python
import base64

# バイナリデータ
data = b"Hello, World!"

# Base64 エンコード
encoded_data = base64.b64encode(data)
print(f"Base64 Encoded: {encoded_data}")
# Base64 Encoded: b'SGVsbG8sIFdvcmxkIQ=='

# Base64 デコード
decoded_data = base64.b64decode(encoded_data)
print(f"Decoded: {decoded_data.decode()}")
# Decoded: Hello, World!
```

<br><br>
- ### 14-6 `binascii` --- バイナリとASCII間の変換
`binascii` モジュールは、バイナリデータと `ASCII` 文字列との間での変換を行うための関数を提供します。このモジュールは、バイナリデータのエンコードやデコード、`ASCII` 文字列の変換に役立ちます。

#### 主な機能
- **`binascii.b2a_hex(bytes)`**: 
バイナリデータを ASCII 文字列の Hex（16進数）表現に変換します。
　　　　
- **`binascii.a2b_hex(bytes or str)`**: 
ASCII 文字列の Hex（16進数）表現をバイナリデータに変換します。
　　　　
- **`binascii.b2a_base64(bytes)`**: 
バイナリデータを Base64 エンコードされた ASCII 文字列に変換します。
　　　　
- **`binascii.a2b_base64(bytes or str)`**: 
Base64 エンコードされた ASCII 文字列をバイナリデータに変換します。
　　　　
- **`binascii.b2a_qp(bytes)`**: 
バイナリデータを Quoted-Printable エンコーディングされた ASCII 文字列に変換します。
　　　　
- **`binascii.a2b_qp(bytes or str)`**: 
Quoted-Printable エンコーディングされた ASCII 文字列をバイナリデータに変換します。
#### 利用例
以下は、バイナリデータを Hex（16進数）表現に変換し、再度バイナリデータに戻す例です。

```python
import binascii

# バイナリデータ
data = b"Hello, World!"

# バイナリデータを Hex に変換
hex_data = binascii.b2a_hex(data)
print(f"Hex Encoded: {hex_data}")
#出力: Hex Encoded: b'48656c6c6f2c20576f726c6421'

# Hex を再度バイナリデータに変換
decoded_data = binascii.a2b_hex(hex_data)
print(f"Decoded: {decoded_data.decode()}")
#出力: Decoded: Hello, World!
```
このコードでは、Hello, World! というバイナリデータを Hex 形式にエンコードし、再度 Hex をデコードして元のバイナリデータに戻しています。


## 15. 構造化マークアップツール
- ### 15-1 `html` --- HTMLサポート
`html` モジュールは、`HTML` のエスケープ処理や、`HTML` のデコード処理をサポートするための機能を提供します。これにより、`HTML` 特有の文字（例: <, >, & など）を安全に処理することができます。

#### 主な機能
- **`html.escape(str)`**: 
特殊な HTML 文字（<, >, & など）をエスケープして、HTML に適した形式に変換します。
　　　　
- **`html.unescape(str)`**: 
エスケープされた HTML 文字（&lt;, &gt;, &amp; など）を元の文字に戻します。
#### 利用例
`html.escape()` を使って、特殊な `HTML` 文字をエスケープし、`html.unescape()` で再度元の文字列に戻す例を紹介します。

```python
import html

# HTML 特殊文字をエスケープ
escaped_string = html.escape('<div>Hello & Welcome</div>')
print(f"Escaped: {escaped_string}")
#出力:Escaped: &lt;div&gt;Hello &amp; Welcome&lt;/div&gt;


# エスケープされた文字列を元に戻す
unescaped_string = html.unescape(escaped_string)
print(f"Unescaped: {unescaped_string}")
#出力:Unescaped: <div>Hello & Welcome</div>
```

<br><br>
- ### 15-2 `html.parser` --- HTMLパーサー
`html.parser` モジュールは、`HTML` コンテンツを解析するためのパーサーを提供します。このモジュールは、`HTML`ドキュメントをツリー構造に変換し、タグや属性などの情報を操作するために使用できます。

#### 主な機能
- **`html.parser()`**: 
`HTML` ドキュメントを解析するための組み込みのパーサー。`HTMLParser` クラスを提供し、`HTML` を解析してツリー構造に変換します。
    　　　　

- **`HTMLParser.feed(data)`**: data を解析して、HTML のタグや属性を処理します。
　　　　
- **`HTMLParser.handle_starttag(tag, attrs)`**: 
開始タグを検出したときに呼び出されるメソッド。
　　　　
- **`HTMLParser.handle_endtag(tag)`**: 終了タグを検出したときに呼び出されるメソッド。
　　　　
- **`HTMLParser.handle_startendtag(tag, attrs)`**: 
自己終了タグを検出したときに呼び出されるメソッド。
#### 利用例
以下は、`html.parser` を使って簡単な `HTML` ドキュメントを解析し、タグの内容を抽出する例です。

```python
from html.parser import HTMLParser

# HTMLParser のサブクラスを作成
class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print(f"Start tag: {tag}")
    
    def handle_endtag(self, tag):
        print(f"End tag: {tag}")
    
    def handle_startendtag(self, tag, attrs):
        print(f"Self-closing tag: {tag}")

# HTML のサンプル
html_data = "<html><body><h1>Hello, World!</h1><br></body></html>"

# HTMLParser を使って解析
parser = MyHTMLParser()
parser.feed(html_data)
```
出力
```
Start tag: html
Start tag: body
Start tag: h1
End tag: h1
Start tag: br
End tag: body
End tag: html
```

<br><br>
- ### 15-3 `html.entities` --- HTML実体定義
`html.entities` モジュールは、`HTML` の文字実体（HTML entities）の名前とコードを定義した辞書を提供します。このモジュールを使用することで、`HTML` における特殊文字を実体参照に変換したり、逆に実体参照を元の文字に戻したりすることができます。

#### 主な機能
- **`html.entities.name2codepoint(name)`**: 
`HTML`の実体名から対応する `Unicode` コードポイントへのマッピングを提供します。
　　　　
- **`html.entities.codepoint2name(int)`**: 
`Unicode` コードポイントから対応する `HTML` 実体名へのマッピングを提供します。
#### 利用例
`html.entities.name2codepoint `を使用して、`HTML `の実体名を対応する `Unicode `コードポイントに変換する例を紹介します。

```python
import html.entities

# HTML 実体名からコードポイントを取得
entity_name = "amp"
codepoint = html.entities.name2codepoint.get(entity_name)
print(f"Entity name: {entity_name}, Codepoint: {hex(codepoint)}")
#出力:Entity name: amp, Codepoint: 0x26

# コードポイントから実体名を取得
unicode_codepoint = 0x26  # &amp; のコードポイント
entity_name = html.entities.codepoint2name.get(unicode_codepoint)
print(f"Codepoint: {hex(unicode_codepoint)}, Entity name: {entity_name}")
#出力:Entity name: amp, Codepoint: 0x26
```
このコードでは、`amp`という実体名を対応するコードポイントに変換し、逆にコードポイント 0x26 から実体名を取得しています。

<br><br>

- ### 15-4 `xml.etree.ElementTree` --- ElementTree XML API
`xml.etree.ElementTree` モジュールは、`XML` ドキュメントを処理するためのシンプルで効率的な API を提供します。このモジュールを使用することで、XML データの解析、操作、生成を簡単に行うことができます。

#### 主な機能
- **`ElementTree クラス`**: XML ドキュメント全体を木構造（ツリー）として表現するクラスです。
- **`Element クラス`**: XML ドキュメントの個々の要素（タグ）を表現するクラスです。
<br>

- **`xml.etree.ElementTree.parse(source)`**:
 XML ファイルを解析して ElementTree オブジェクトを生成します。
   　　　　　 
- **`xml.etree.ElementTree.Element(element)`**: 新しい XML 要素を作成します。
 　　　　   
- **`xml.etree.ElementTree.tostring(element)`**: 
Element オブジェクトを文字列（XML）に変換します。
　　　　
- **`xml.etree.ElementTree.write(file)`**: ElementTree オブジェクトをファイルに書き出します。
#### 利用例
以下は、`XML` ドキュメントを解析し、要素を操作する基本的な例です。

```python
import xml.etree.ElementTree as ET

# XML データを解析して ElementTree オブジェクトを作成
xml_data = '''<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>'''

root = ET.fromstring(xml_data)

# ルート要素を表示
print(f"Root element: {root.tag}")
#出力:# Root element: note

# 子要素を表示
for child in root:
    print(f"Child element: {child.tag} - {child.text}")
#出力:
# Child element: to - Tove
# Child element: from - Jani
# Child element: heading - Reminder
# Child element: body - Don't forget me this weekend!

# 新しい要素を追加
new_element = ET.Element("newElement")
new_element.text = "This is a new element"
root.append(new_element)

# XML を文字列に変換
xml_string = ET.tostring(root, encoding="unicode")
print(f"Modified XML: {xml_string}")
#出力:
# Modified XML: <note>
#     <to>Tove</to>
#     <from>Jani</from>
#     <heading>Reminder</heading>
#     <body>Don't forget me this weekend!</body>
#     <newElement>This is a new element</newElement>
# </note>
```

<br><br>
- ### 15-5 `xml.dom` --- ドキュメントオブジェクトモデル API
`xml.dom` モジュールは、`XML` ドキュメントを `DOM`（ドキュメントオブジェクトモデル）形式で操作するための API を提供します。`DOM`は、`XML` ドキュメントをツリー構造として表現し、その構造をプログラムから操作できるようにする技術です。

#### 主な機能
- **`xml.dom.minidom.parse(file)`**: XML ファイルを解析して DOM ツリーを作成します。
　　　　
- **`xml.dom.minidom.parseString(text)`**: 
XML 文字列を解析して DOM ツリーを作成します。
　　　　
- **`xml.dom.minidom.Document.createElement(tag)`**: 新しい XML 要素を作成します。
　　　　
- **`xml.dom.minidom.Document.createTextNode(text)`**: 
新しいテキストノードを作成します。
　　　　
- **`xml.dom.minidom.Document.toprettyxml(indent=" ")`**: DOM ツリーを整形して文字列に変換します。
#### 利用例
以下は、xml.dom.minidom を使って XML を解析し、DOM ツリーを操作する基本的な例です。

```python
from xml.dom import minidom

# XML データの例
xml_data = '''<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>'''

# XML を解析して DOM ツリーを作成
doc = minidom.parseString(xml_data)

# ルート要素の取得
root = doc.documentElement
print(f"Root element: {root.nodeName}")
#出力:# Root element: note

# 子要素の取得
to_element = root.getElementsByTagName('to')[0]
from_element = root.getElementsByTagName('from')[0]
print(f"To: {to_element.firstChild.nodeValue}")
# To: Tove
print(f"From: {from_element.firstChild.nodeValue}")
# From: Jani

# 新しい要素の作成
new_element = doc.createElement('newElement')
new_element.appendChild(doc.createTextNode('This is a new element'))
root.appendChild(new_element)

# 変更後の XML を出力
print("Modified XML:")
print(doc.toprettyxml())
# Modified XML:
# <?xml version="1.0" ?>
# <note>
#     <to>Tove</to>
#     <from>Jani</from>
#     <heading>Reminder</heading>
#     <body>Don't forget me this weekend!</body>
#     <newElement>This is a new element</newElement>
# </note>
```
このコードでは、`minidom.parseString()` を使って XML データを DOM ツリーに変換し、その後要素を取得・操作して新しい要素を追加しています。最後に `toprettyxml()` を使って整形された XML を出力しています。





<br><br>
- ### 15-6 `xml.sax` --- SAXバーサーのサポート
`xml.sax` モジュールは、`SAX（Simple API for XML`バーサーのサポートを提供します。`SAX` は、`XML` ドキュメントをイベント駆動型で逐次的に解析するためのインターフェースであり、メモリ使用量を抑えながら大規模な `XML` ファイルを処理するのに適しています。

#### 主な機能
- **`xml.sax.make_parser()`**: 新しい SAX パーサーを作成します。
　　　　
- **`xml.sax.parse(source)`**: 
XML ファイル（またはファイルライクオブジェクト）を解析します。
　　　　
- **`xml.sax.parseString(text)`**: XML 文字列を解析します。
　　　　
- **`xml.sax.handler.ContentHandler`**: XML のイベント（開始タグ、終了タグ、テキストなど）を処理するための基本クラス。
#### 利用例
以下は、xml.sax を使って XML ドキュメントを逐次的に解析し、タグの開始・終了イベントを処理する例です。

```python
import xml.sax

# ContentHandler のサブクラスを作成
class MyHandler(xml.sax.handler.ContentHandler):
    def startElement(self, name, attrs):
        print(f"Start element: {name}")
    
    def endElement(self, name):
        print(f"End element: {name}")
    
    def characters(self, content):
        print(f"Content: {content}")

# XML データ
xml_data = '''<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>'''

# SAX パーサーを作成
parser = xml.sax.make_parser()

# イベントハンドラーを設定
handler = MyHandler()
parser.setContentHandler(handler)

# XML データを解析
from io import StringIO
xml_file = StringIO(xml_data)
parser.parse(xml_file)
```
このコードでは、`ContentHandler` をサブクラス化して、`XML `のタグ開始、タグ終了、テキストを処理するイベントメソッドを定義しています。`xml.sax.make_parser()` を使って `SAX パーサー`を作成し、`parse()`メソッドで `XML` を解析しています。



<br><br>

## 16. インターネットプロトコルとサポート
- ### 16-1 `webbrowser` --- ウェブブラウザコントローラー
`webbrowser` モジュールは、ウェブブラウザを操作するための簡単なインターフェースを提供します。このモジュールを使用することで、ユーザーのデフォルトウェブブラウザを使って URL を開くことができます。

#### 主な機能
- **`webbrowser.open(url)`**: 指定した URL をデフォルトのウェブブラウザで開きます。
　　　　
- **`webbrowser.open_new(url)`**: 
新しいウィンドウまたはタブで URL を開きます（ブラウザが対応している場合）。
　　　　
- **`webbrowser.open_new_tab(url)`**: 
新しいタブで URL を開きます（ブラウザが対応している場合）。
　　　　
- **`webbrowser.get(using=None)`**: 
指定したブラウザを使って URL を開くためのブラウザコントローラーを取得します。
　　　　
- **`webbrowser.register(name, constructor, instance=None)`**: 
新しいブラウザを登録します。
#### 利用例
以下は、`webbrowser` モジュールを使って指定した URL をブラウザで開く基本的な例です。

```python
import webbrowser

# URL をデフォルトのブラウザで開く
url = "https://www.python.org"
webbrowser.open(url)

# 新しいタブで URL を開く
webbrowser.open_new_tab(url)

# 新しいウィンドウで URL を開く
webbrowser.open_new(url)
```
このコードでは、`open`、`open_new_tab`、`open_new` を使って URL を異なる方法で開いています。`open` はデフォルトのブラウザで URL を開き、open_new_tab は新しいタブで、open_new は新しいウィンドウで URL を開きます。



<br><br>

- ### 16-2 `urllib` --- URL操作
`urllib`モジュールは、URL の操作に関連するさまざまな機能を提供します。URL の解析、構築、エンコード/デコード、リクエスト送信など、ウェブ関連の作業を効率的に行うためのツールを備えています。

#### 主な機能
- **`urllib.parse.urlparse(url)`**: 
URL を構成要素に分解して ParseResult オブジェクトを返します。
　　　　
- **`urllib.parse.urlunparse(parts)`**: 
URL の構成要素を組み合わせて、元の URL を再構築します。
　　　　
- **`urllib.parse.urlencode(query)`**: クエリパラメータを URL エンコードします。
　　　　
- **`urllib.parse.parse_qs(query)`**: クエリ文字列を辞書形式に解析します。
　　　　
- **`urllib.request.urlopen(url)`**: 
URL にリクエストを送信し、そのレスポンスを返します。
　　　　
- **`urllib.request.Request(url, data=None, headers={})`**: 
カスタム HTTP リクエストを作成します。
#### 利用例
以下は、`urllib.parse` を使って URL を解析する基本的な例です。

```python
import urllib.parse

# URL の解析
url = "https://www.example.com:80/path/to/page?name=JohnDoe&age=30#section"
parsed_url = urllib.parse.urlparse(url)

# 解析結果の表示
print(f"Scheme: {parsed_url.scheme}")
print(f"Netloc: {parsed_url.netloc}")
print(f"Path: {parsed_url.path}")
print(f"Query: {parsed_url.query}")
print(f"Fragment: {parsed_url.fragment}")
print(f"Params: {parsed_url.params}")
# 出力: 
#Scheme: https
#Netloc: www.example.com:80
#Path: /path/to/page
#Query: name=JohnDoe&age=30
#Fragment: section
#Params: 


# URL の構築
url_parts = {
    'scheme': 'https',
    'netloc': 'www.example.com',
    'path': '/path/to/page',
    'query': 'name=JohnDoe&age=30',
    'fragment': 'section'
}
constructed_url = urllib.parse.urlunparse(url_parts)
print(f"Constructed URL: {constructed_url}")
#出力:Constructed URL: https://www.example.com/path/to/page?name=JohnDoe&age=30#section

```
このコードでは、`urlparse()` を使って URL を解析し、その各部分（スキーム、ネットロケーション、パス、クエリ、フラグメント）を表示しています。また、`urlunparse()` を使って解析した部品から URL を再構築しています。




<br><br>
 - ### 16-3 `http` --- HTTPモジュール群
 `http` モジュール群は、HTTP プロトコルに関連するさまざまな操作をサポートする機能を提供します。HTTP リクエストやレスポンスの処理、ヘッダーの操作、ステータスコードの管理など、ウェブ通信を効率的に行うために必要なツールが集約されています。

#### 主な機能
- **`http.client.HTTPSConnection(host, port)`**: HTTPS 接続を作成します。
　　　　
- **`http.client.HTTPResponse(fp)`**: HTTP レスポンスを表すクラス。レスポンスのステータスやヘッダー、ボディを処理します。
　　　　
- **`http.server.BaseHTTPRequestHandler(request, client_address, server)`**: HTTP リクエストを処理するための基本クラス。サーバーを構築する際に使用します。
　　　　
- **`http.cookies.SimpleCookie(cookie_string)`**: HTTP クッキーを作成、操作するためのクラス。
　　　　
- **`http.HTTPStatus()`**: HTTP ステータスコードを表すクラス。例えば HTTPStatus.OK（200）や HTTPStatus.NOT_FOUND（404）など。
#### 利用例
以下は、http.client モジュールを使って HTTP リクエストを送信し、レスポンスを取得する基本的な例です。

```python
import http.client

# サーバーへの接続
connection = http.client.HTTPSConnection("www.example.com")

# HTTP リクエストの送信
connection.request("GET", "/")

# レスポンスの取得
response = connection.getresponse()

# レスポンスの内容を表示
print(f"Status: {response.status}")
print(f"Reason: {response.reason}")
print(f"Headers: {response.getheaders()}")
print(f"Body: {response.read().decode()}")
#出力:
#Status: 200
#Reason: OK
#Headers: [('date', 'Tue, 19 Dec 2023 12:00:00 GMT'), ('expires', '-1'), ('cache-control', 'private, max-age=0, must-revalidate'), ...]
#Body: <!doctype html><html><head><title>Google</title></head><body>...</body></html>

# 接続のクローズ
connection.close()
```
このコードでは、http.client.HTTPSConnection を使って HTTPS サーバーに接続し、`request()` メソッドで HTTP リクエストを送信しています。その後、`getresponse()` メソッドを使ってレスポンスを受け取り、各情報（ステータスコード、レスポンスボディ）を表示しています。




<br><br>
- ### 16-4 `ftplib` --- FTPクライアント
`ftplib` モジュールは、FTP（File Transfer Protocol）サーバーと通信し、ファイルのアップロードやダウンロードを行うためのツールを提供します。FTP クライアントとして機能し、リモートサーバーとのファイル転送を簡単に行うことができます。

#### 主な機能
- **`FTP(host)`**: 指定したホストに接続するための FTP オブジェクトを作成します。
　　　　
- **`FTP.login(user='', passwd='', acct='')`**: FTP サーバーにログインします。デフォルトでは匿名ログインが行われます。
　　　　

- **`FTP.quit()`**: FTP セッションを終了します。
　　　　
- **`FTP.cwd(path)`**: リモートサーバー上のディレクトリを変更します。
　　　　
- **`FTP.retrbinary(cmd, callback, blocksize=8192)`**: 
バイナリモードでファイルをダウンロードします。
　　　　
- **`FTP.storbinary(cmd, file, blocksize=8192)`**: バイナリモードでファイルをアップロードします。
　　　　
- **`FTP.retrlines(cmd, callback)`**: テキストモードでファイルをダウンロードします。
　　　　
- **`FTP.storlines(cmd, file)`**: テキストモードでファイルをアップロードします。
　　　　
- **`FTP.mkd(path)`**: サーバー上でディレクトリを作成します。
　　　　
- **`FTP.rmd(path)`**: サーバー上でディレクトリを削除します。
#### 利用例
以下は、ftplib を使って FTP サーバーに接続し、ファイルをダウンロードする基本的な例です。

```python
from ftplib import FTP

# FTP サーバーに接続
ftp = FTP('ftp.example.com')

# ログイン（匿名ログインの場合はユーザー名「anonymous」を指定）
ftp.login()

# ファイルをダウンロード（バイナリモード）
with open('example.txt', 'wb') as local_file:
    ftp.retrbinary('RETR example.txt', local_file.write)

# 接続を閉じる
ftp.quit()
```
このコードでは、FTP クラスを使って FTP サーバーに接続し、`retrbinary()` メソッドを使ってファイルをダウンロードしています。`retrbinary()` はバイナリモードでの転送に使用されます。`quit()` メソッドで接続を閉じます。



<br><br>
- ### 16-5 `smtplib` --- SMTPクライアント
`smtplib` モジュールは、SMTP（Simple Mail Transfer Protocol）を使用して、電子メールを送信するためのツールを提供します。SMTP サーバーと通信し、メールの送信を自動化するために使用できます。

#### 主な機能
- **`smtplib.SMTP(host, port)`**: SMTP サーバーに接続するためのクラス。
　　　　
- **`SMTP.sendmail(from_addr, to_addrs, msg)`**: 
メールを送信します。from_addr は送信元、to_addrs は送信先、msg はメッセージの内容です。
　　　　
- **`SMTP.login(user, password)`**: SMTP サーバーにログインします。
　　　　
- **`SMTP.quit()`**: SMTP セッションを終了します。
　　　　
- **`SMTP.starttls()`**: 
SMTP サーバーとの通信を暗号化するためのメソッドです。通常、ポート 587 を使用する際に必要です。
　　　　
- **`SMTP.set_debuglevel(level)`**: 
デバッグ情報を出力するためのメソッドです。level=1 で詳細なデバッグ情報が表示されます。

#### 利用例
以下は、`smtplib` を使用して Gmail の SMTP サーバーを介して電子メールを送信する基本的な例です。

```python
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# メールの内容を作成
msg = MIMEMultipart()
msg['From'] = 'your_email@gmail.com'
msg['To'] = 'recipient_email@example.com'
msg['Subject'] = 'Test Email'

# メール本文を設定
body = 'This is a test email sent via Python.'
msg.attach(MIMEText(body, 'plain'))

# Gmail の SMTP サーバーに接続
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()  # 暗号化通信の開始

# ログイン（Gmail の場合、アプリケーション固有のパスワードが必要）
server.login('your_email@gmail.com', 'your_password')

# メールを送信
server.sendmail(msg['From'], msg['To'], msg.as_string())

# サーバーから切断
server.quit()
```
このコードでは、smtplib.SMTP を使用して Gmail の SMTP サーバーに接続し、`sendmail()`メソッドを使用してメールを送信しています。MIMEText と MIMEMultipart を使用して、メールの本文とヘッダーを構築しています。



<br><br>
- ### 16-6 `xmlrpc` --- XML-RPCサーバーとクライアント
`xmlrpc` モジュールは、`XML-RPC`（Remote Procedure Call）プロトコルを使用して、リモートプロシージャの呼び出しを行うためのツールを提供します。XML-RPC を利用することで、ネットワーク越しに異なるコンピュータ間で関数呼び出しを実行でき、簡単な分散システムを構築することができます。

#### 主な機能
- **`xmlrpc.client.ServerProxy(url)`**: 
XML-RPC サーバーへのプロキシ（代理）オブジェクト。リモート関数をローカル関数のように呼び出せるようにします。
　　　　
- **`xmlrpc.client.MultiCall(url)`**:
 複数の XML-RPC リクエストを一度に送信するためのクラス。
　　　　
- **`xmlrpc.server.SimpleXMLRPCServer(addr)`**: 
基本的な XML-RPC サーバーの実装を提供します。リモート関数を簡単に登録できます。
　　　　
- **`xmlrpc.server.SimpleXMLRPCRequestHandler(allow_none, encoding)`**: 
リクエストのハンドリングをカスタマイズするためのクラス。
#### 利用例
以下は、xmlrpc.client を使って XML-RPC サーバーにリクエストを送るクライアント側の基本的な例です。

クライアント側コード
```python
import xmlrpc.client

# サーバーの URL に接続
server = xmlrpc.client.ServerProxy('http://localhost:8000')

# サーバー上の関数を呼び出し
result = server.add(5, 3)

# 結果を表示
print(f"Result of add(5, 3): {result}")
#出力:Result of add(5, 3): 8
```
このコードでは、xmlrpc.client.ServerProxy を使用して、ローカルの XML-RPC サーバーに接続し、サーバー上の `add` 関数を呼び出しています。

次に、サーバー側のコードです。

サーバー側コード
```python
from xmlrpc.server import SimpleXMLRPCServer

# 足し算を行う関数
def add(x, y):
    return x + y

# サーバーの作成
server = SimpleXMLRPCServer(('localhost', 8000))

# 関数をサーバーに登録
server.register_function(add, 'add')

# サーバーの開始
print("Server is running...")
server.serve_forever()
#出力:Server is running...
```
このコードでは、`xmlrpc.server.SimpleXMLRPCServer` を使用してサーバーを起動し、`add` 関数をリモート呼び出し可能にしています。



<br><br>
- ### 16-7 `ipaddress` --- IPv4/IPv6操作
`ipaddress` モジュールは、IPv4 および IPv6 アドレスの操作を簡単に行うためのツールを提供します。このモジュールを使用すると、IP アドレスの解析、検証、ネットワークの計算、サブネットマスクの操作などが可能です。ネットワーク関連のプログラミングを行う際に非常に便利なモジュールです。

#### 主な機能
- **`ipaddress.IPv4Address(adress)`**: IPv4 アドレスを表すクラス。
　　　　
- **`ipaddress.IPv6Address(adress)`**: IPv6 アドレスを表すクラス。
　　　　　
- **`ipaddress.IPv4Network(network)`**: IPv4 のネットワークを表すクラス。
　　　　
- **`ipaddress.IPv6Network(network)`**: IPv6 のネットワークを表すクラス。
　　　　
- **`ipaddress.IPv4Interface(interface)`**: IPv4 のインターフェースを表すクラス。
　　　　
- **`ipaddress.IPv6Interface(interface)`**: IPv6 のインターフェースを表すクラス。
　　　　
- **`アドレスの検証`**: IP アドレスが有効かどうかを確認できます。
　　　　
- **`サブネットの操作`**: ネットワークアドレス、ホストアドレスの計算、サブネットのサイズの確認が可能です。
#### 利用例
以下は、ipaddress モジュールを使って IPv4 および IPv6 アドレスを操作する基本的な例です。

IPv4 アドレスの操作
```python
import ipaddress

# IPv4 アドレスの作成
ip = ipaddress.IPv4Address('192.168.1.1')

# アドレスの表示
print(f"IP Address: {ip}")
print(f"Is private: {ip.is_private}")  # プライベートアドレスかどうか
print(f"Is global: {ip.is_global}")  # グローバルアドレスかどうか
#出力:
#IP Address: 192.168.1.1
#Is private: True
#Is global: False
```
IPv6 アドレスの操作
```python
import ipaddress

# IPv6 アドレスの作成
ip = ipaddress.IPv6Address('2001:0db8:85a3:0000:0000:8a2e:0370:7334')

# アドレスの表示
print(f"IP Address: {ip}")
print(f"Is private: {ip.is_private}")  # プライベートアドレスかどうか
#出力:
#IP Address: 2001:db8:85a3::8a2e:370:7334
#Is private: True
```
IPv4 ネットワークの操作
```python
import ipaddress

# IPv4 ネットワークの作成
network = ipaddress.IPv4Network('192.168.1.0/24')

# ネットワーク情報を表示
print(f"Network: {network}")
print(f"Network Address: {network.network_address}")
print(f"Broadcast Address: {network.broadcast_address}")
#出力:
#Network: 192.168.1.0/24
#Network Address: 192.168.1.0
#Broadcast Address: 192.168.1.255

# ネットワーク内の全てのホストをリストアップ
for host in network.hosts():
    print(host)
#出力:
#Broadcast Address: 192.168.1.255
#192.168.1.1
#192.168.1.2
#192.168.1.3
#192.168.1.4
#    .
#    .
#    .
```


## 17. マルチメディアサービス
 - ### 17-1 `wave` --- WAVファイルの読み書き
 `wave` モジュールは、WAV ファイルの読み書きを行うためのツールを提供します。WAV ファイルは、音声データを格納するためのフォーマットであり、wave モジュールを使うことで、これらのファイルをプログラム内で簡単に扱うことができます。

#### 主な機能
- **`wave.open(filename, mode)`**: 
WAV ファイルを開くための関数。filename にはファイル名、mode にはモード（'r' で読み込み、'w' で書き込み）を指定します。

- **`Wave_read()`**: WAV ファイルの読み込み用クラス。
　　　　
- **`Wave_write()`**: WAV ファイルの書き込み用クラス。
　　　　
- **`getparams()`**: 
WAV ファイルのメタデータ（チャンネル数、サンプリングレートなど）を取得するメソッド。
　　　　　
- **`writeframes(data)`**: 音声データを WAV ファイルに書き込むメソッド。
#### 利用例
WAV ファイルの読み込み
```python
import wave

# WAV ファイルを読み込みモードで開く
with wave.open('example.wav', 'r') as wf:
    # ファイルのパラメータ（チャンネル数、サンプル幅、サンプリングレートなど）を取得
    params = wf.getparams()
    print(f"チャンネル数: {params.nchannels}")
    print(f"サンプル幅: {params.sampwidth} バイト")
    print(f"サンプリングレート: {params.framerate} Hz")
    print(f"フレーム数: {params.nframes}")
    #出力例:
    #チャンネル数: 2
    #サンプル幅: 2 バイト
    #サンプリングレート: 44100 Hz
    #フレーム数: 88200
    
    # 音声データを読み込む
    audio_data = wf.readframes(params.nframes)
    print(f"読み込んだ音声データの長さ: {len(audio_data)} バイト")
    #出力:読み込んだ音声データの長さ: 176400 バイト
```
WAV ファイルの書き込み
```python
import wave
import numpy as np

# 新しい WAV ファイルを作成
with wave.open('output.wav', 'w') as wf:
    # チャンネル数、サンプル幅（16ビット）、サンプリングレートを設定
    wf.setnchannels(1)  # モノラル
    wf.setsampwidth(2)  # 16ビット
    wf.setframerate(44100)  # 44.1 kHz

    # サンプルデータを作成（例えば、1秒間のサイン波）
    duration = 1  # 秒
    frequency = 440  # Hz（A4の音）
    samples = np.sin(2 * np.pi * np.arange(44100 * duration) * frequency / 44100)
    samples = np.int16(samples * 32767)  # 16ビットの整数に変換

    # 音声データを書き込む
    wf.writeframes(samples.tobytes())
```
<br><br>
 - ### 17-2 `colorsys` --- 色体系間の変換
 `colorsys` モジュールは、異なる色体系（例えば RGB や HSV）の間で色を変換するための関数を提供します。色の表現方法を変換する際に非常に便利で、グラフィックや画像処理の分野でよく使用されます。

#### 主な機能
- **`rgb_to_hsv(r, g, b)`**: 
RGB 値を HSV に変換します。各引数 r, g, b は 0〜1 の範囲で指定します。
　　　　
- **`hsv_to_rgb(h, s, v)`**: 
HSV 値を RGB に変換します。引数 h, s, v はそれぞれ 0〜1 の範囲で指定します。
　　　　
- **`rgb_to_hls(r, g, b)`**: RGB 値を HLS に変換します。
　　　　
- **`hls_to_rgb(h, l, s)`**: HLS 値を RGB に変換します。
#### 利用例
RGB から HSV への変換
```python
import colorsys

# RGB 値（0〜1の範囲）
r, g, b = 0.5, 0.3, 0.7

# RGB を HSV に変換
h, s, v = colorsys.rgb_to_hsv(r, g, b)

print(f"RGB({r}, {g}, {b}) -> HSV({h}, {s}, {v})")
#出力:RGB(0.5, 0.3, 0.7) -> HSV(0.75, 0.5714285714285714, 0.7)
```
HSV から RGB への変換
```python
import colorsys

# HSV 値
h, s, v = 0.7, 0.6, 0.9

# HSV を RGB に変換
r, g, b = colorsys.hsv_to_rgb(h, s, v)

print(f"HSV({h}, {s}, {v}) -> RGB({r}, {g}, {b})")
#出力:HSV(0.7, 0.6, 0.9) -> RGB(0.46799999999999964, 0.36000000000000004, 0.9)
```
RGB から HLS への変換
```python
import colorsys

# RGB 値（0〜1の範囲）
r, g, b = 0.4, 0.6, 0.2

# RGB を HLS に変換
h, l, s = colorsys.rgb_to_hls(r, g, b)

print(f"RGB({r}, {g}, {b}) -> HLS({h}, {l}, {s})")
#出力:RGB(0.4, 0.6, 0.2) -> HLS(0.25, 0.4, 0.49999999999999994)
```
HLS から RGB への変換
```python
import colorsys

# HLS 値
h, l, s = 0.2, 0.5, 0.7

# HLS を RGB に変換
r, g, b = colorsys.hls_to_rgb(h, l, s)

print(f"HLS({h}, {l}, {s}) -> RGB({r}, {g}, {b})")
#出力:HLS(0.2, 0.5, 0.7) -> RGB(0.7099999999999999, 0.85, 0.15000000000000002)

```


 ## 18. 国際化
- ### 18-1 `gettext` --- 多言語国際化サービス
 `gettext` モジュールは、ソフトウェアアプリケーションの多言語対応（国際化）を簡単に実現するためのツールを提供します。このモジュールは、文字列の翻訳を行うための仕組みを提供し、ユーザーが使用する言語に応じて適切なメッセージを表示するために使用されます。

#### 主な機能
- **`gettext.translation(domain, localedir, languages)`**: 
指定したドメインとロケールディレクトリ、使用する言語を基に翻訳オブジェクトを作成します。
　　　　
- **`gettext(text)`**: 翻訳対象の文字列を取得します。翻訳が存在しない場合、元の文字列が返されます。
　　　　　　　　
- **`ngettext(singular, plural, n)`**: 単数形と複数形のメッセージを選択します。n の値に基づいて適切な翻訳が返されます。
　　　　
- **`textdomain(domain)`**: 現在使用する翻訳ドメインを設定します。異なるモジュールやアプリケーションが異なる翻訳ファイルを使用できるようにします。
　　　　
- **`install()`**: アプリケーションに対して翻訳をインストールし、翻訳関数を簡単に利用できるようにします。
#### 利用例
基本的な翻訳の使用
```python
import gettext

# 翻訳ファイルの読み込み(翻訳用の辞書ファイルはlocalesディレクトリ以下に置く必要がある)
t = gettext.translation('myapp', localedir='locales', languages=['ja'])
t.install()

# 翻訳を取得
print(_('Hello, world!'))  # "Hello, world!" の日本語翻訳が表示される
# 出力:こんにちは、世界！
```

<br><br>
- ### 18-2 `locale` --- ロケールベースの設定
`locale` モジュールは、ロケールに基づいた地域ごとの設定を扱うための機能を提供します。ロケールとは、特定の言語や文化に基づいた設定（例えば、日付の形式、通貨記号、数字の区切り記号など）を指し、これに基づいてプログラムの動作を調整するために使用されます。

#### 主な機能

- **`setlocale(category, locale)`**: 
ロケールの設定を変更します。`category` には日付、数値、通貨などの設定を指定し、`locale` には使用したいロケールを指定します。
　　　　　　　
- **`getlocale(category)`**: 現在設定されているロケールを取得します。
　　　　
- **`localeconv()`**: 数値のロケールに基づく書式を辞書として取得します。
　　　　
- **`strcoll(str1, str2)`**: ロケールに基づいた文字列の比較を行います。
#### 利用例
ロケールの設定と取得
```python
import locale

# ロケールを日本語に設定
locale.setlocale(locale.LC_ALL, 'ja_JP.UTF-8')

# 現在のロケールを取得
current_locale = locale.getlocale()
print(f"現在のロケール: {current_locale}")
#出力:macos:現在のロケール: ('ja_JP', 'UTF-8')
#   windows:現在のロケール: ('ja_JP', 'cp932')
```
数値のロケールに基づいたフォーマット
```python
import locale

# ロケールを日本語に設定
locale.setlocale(locale.LC_NUMERIC, 'ja_JP.UTF-8')

# ロケールに基づいた数値のフォーマット
formatted_number = locale.format_string("%f", 12345.6789, grouping=True)
print(f"フォーマットされた数値: {formatted_number}")
#出力:フォーマットされた数値: 12,345.678900
#設定できてない場合:locale.Error: unsupported locale setting
```
通貨のロケールに基づいたフォーマット
```python
import locale

# ロケールをアメリカに設定
locale.setlocale(locale.LC_MONETARY, 'en_US.UTF-8')

# 通貨に基づいたフォーマット
formatted_currency = locale.currency(12345.6789)
print(f"フォーマットされた通貨: {formatted_currency}")
#出力:フォーマットされた通貨: $12,345.68
```
日付と時刻のロケールに基づく処理
```python
import locale
import time

# ロケールをフランスに設定
locale.setlocale(locale.LC_TIME, 'fr_FR.UTF-8')

# 日付をロケールに基づいてフォーマット
formatted_date = time.strftime("%A, %d %B %Y")
print(f"フォーマットされた日付: {formatted_date}")
#フランス語ロケールが設定できた場合（例: macOS または Linux）
#出力:フォーマットされた日付: vendredi, 19 décembre 2024
```



<br><br>


## 19. プログラムのフレームワーク
   - ### 19-1 `turtle` --- タートルグラフィックス
`turtle` モジュールは、グラフィカルな操作を通してプログラミングの基本を学ぶためのツールを提供します。

タートルグラフィックスは、亀（タートル）を使って図形を描くというコンセプトに基づいており、直感的にグラフィックスを操作することができます。このモジュールは、特に教育用途で広く使われています。

#### 主な機能
- **`turtle.forward(distance)`**: タートルを指定された距離だけ前に進ませます。
　　　　
- **`turtle.backward(distance)`**: タートルを指定された距離だけ後ろに進ませます。
　　　　
- **`turtle.right(angle)`**: タートルを指定された角度だけ右に回転させます。
　　　　
- **`turtle.left(angle)`**: タートルを指定された角度だけ左に回転させます。
　　　　　
- **`turtle.penup()`**: ペンを持ち上げて、移動中に線を描かないようにします。
　　　　
- **`turtle.pendown()`**: ペンを下ろして、描画を再開します。
　　　　
- **`turtle.color(color)`**: ペンの色を指定します。
　　　　
- **`turtle.shape(shape)`**: タートルの形状を指定します（デフォルトは亀型）。
　　　　
- **`turtle.speed(speed)`**: タートルの移動速度を設定します（0 = 最速、10 = 最遅）。
　　　　
- **`turtle.hideturtle()`**: タートルを画面から隠します。
　　　　
- **`turtle.showturtle()`**: タートルを画面に表示します。
#### 利用例
基本的な描画
```python
import turtle

# タートル画面を設定
t = turtle.Turtle()

# タートルが移動する
t.forward(100)  # 100ピクセル前進
t.left(90)      # 90度左に回転
t.forward(100)  # 100ピクセル前進

# 描画終了
turtle.done()
```
複雑な図形の描画
```python
import turtle

# タートル画面を設定
t = turtle.Turtle()

# 正方形を描く
for _ in range(4):
    t.forward(100)
    t.left(90)

# 描画終了
turtle.done()
```
カラフルな図形
```python
import turtle

# タートル画面を設定
t = turtle.Turtle()

# 色を変更しながら円を描く
colors = ['red', 'green', 'blue', 'yellow']
for color in colors:
    t.color(color)
    t.forward(100)
    t.left(90)

# 描画終了
turtle.done()
```
速さの調整
```python
import turtle

# タートル画面を設定
t = turtle.Turtle()

# 速度を最速に設定
t.speed(0)

# 螺旋を描く
for _ in range(36):
    t.forward(100)
    t.left(170)

# 描画終了
turtle.done()
```


 <br><br>
- ### 19-2 `cmd` --- 行指向コマンドインタープリター
`cmd` モジュールは、コマンドラインインターフェース（CLI）を作成するためのツールを提供します。

これにより、ユーザーがターミナルでコマンドを入力し、インタラクティブに操作できるようなアプリケーションを構築することができます。cmd モジュールは、簡単なコマンドラインアプリケーションから複雑なインタラクティブなツールまで、さまざまなアプリケーションの作成に役立ちます。

#### 主な機能　　　　
- **`Cmd クラス`**: コマンドインターフェースを作成するための基底クラス。
<br>

- **`cmdloop()`**: コマンドラインループを開始し、ユーザーの入力を待機します。
　　　　
- **`default(line)`**: 
ユーザーが入力したコマンドに対応するメソッドが存在しない場合に呼ばれます。
　　　　
- **`do_<command_name>(self, arg)`**: 
<command_name> というコマンドが入力されたときに実行されるメソッド。コマンドに対応するメソッドを定義することで、ユーザー入力に応じた処理を実行できます。
　　　　
- **`help_<command_name>(self)`**: 
特定のコマンドに対するヘルプを提供するメソッド。コマンドに関する説明を表示します。
　　　　
- **`precmd(line)`**: 
ユーザーがコマンドを入力する前に処理を行いたい場合にオーバーライドします。
　　　　
- **`postcmd(stop, line)`**: コマンド実行後に処理を行いたい場合にオーバーライドします。
#### 利用例
基本的なコマンドインタープリター
```python
import cmd

class MyCmd(cmd.Cmd):
    prompt = '> '  # プロンプトを設定

    def do_greet(self, name):
        """greet コマンド: ユーザーを挨拶する"""
        print(f"Hello, {name}!")

    def do_exit(self, arg):
        """exit コマンド: インタープリターを終了"""
        print("Goodbye!")
        return True  # コマンドインタープリターを終了

# コマンドインタープリターを開始
if __name__ == '__main__':
    MyCmd().cmdloop()
```    
このプログラムを実行すると、greet や exit コマンドを入力することで、インタラクティブに操作できます。

```plaintext
> greet Alice
Hello, Alice!
> exit
Goodbye!
```
コマンドのヘルプ
コマンドにヘルプを追加することもできます。例えば、do_greet メソッドに help_greet を追加して、greet コマンドに関するヘルプを提供することができます。

```python
import cmd

class MyCmd(cmd.Cmd):
    prompt = '> '  # プロンプトを設定

    def do_greet(self, name):
        """greet コマンド: ユーザーを挨拶する"""
        print(f"Hello, {name}!")

    def help_greet(self):
        """greet コマンドのヘルプ"""
        print("Usage: greet <name>")
        print("Greets the user with the specified name.")

    def do_exit(self, arg):
        """exit コマンド: インタープリターを終了"""
        print("Goodbye!")
        return True  # コマンドインタープリターを終了

# コマンドインタープリターを開始
if __name__ == '__main__':
    MyCmd().cmdloop()
```
help greet と入力すると、以下のようなヘルプが表示されます。

```plaintext
> help greet
Usage: greet <name>
Greets the user with the specified name.
```
コマンドの補完
コマンドの補完機能を使うことで、ユーザーがコマンドを入力する際に候補を提供することができます。`cmd`モジュールでは `complete_<command_name>` メソッドを使って、コマンドの補完を実装できます。

```python
import cmd

class MyCmd(cmd.Cmd):
    prompt = '> '  # プロンプトを設定

    def do_greet(self, name):
        """greet コマンド: ユーザーを挨拶する"""
        print(f"Hello, {name}!")

    def complete_greet(self, text, line, begidx, endidx):
        """greet コマンドの補完"""
        names = ['Alice', 'Bob', 'Charlie', 'David']
        return [name for name in names if name.startswith(text)]

    def do_exit(self, arg):
        """exit コマンド: インタープリターを終了"""
        print("Goodbye!")
        return True  # コマンドインタープリターを終了

# コマンドインタープリターを開始
if __name__ == '__main__':
    MyCmd().cmdloop()
```
greet コマンドを入力し始めると、補完候補が表示されます。

```plaintext
> greet A
Alice  Bob
> greet C
Charlie
```

<br><br>
- ### 19-3 `shlex` --- 簡易字句解析
`shlex` モジュールは、シェルコマンドの引数を解析するためのツールを提供します。このモジュールは、シェルスクリプトやコマンドラインの引数を正確に分解するための簡易的な字句解析を行います。shlex を使用することで、コマンドの引数をスペースで分割し、適切に引用符で囲まれた文字列やエスケープシーケンスを処理することができます。

#### 主な機能
- **`shlex.split(string)`**:
引数として渡された文字列を、シェルスタイルで分割し、リストとして返します。引数に引用符が含まれている場合、それを正しく扱い、必要な部分だけを分割します。
　　　　
- **`shlex.quote(string)`**:
引数の文字列をシェルで安全に使用できる形式にエスケープします。シェルコマンドに渡すために引数を適切に引用符で囲んだ形式で返します。
　　　　
- **`shlex.shlex クラス`**:
`shlex` モジュールの基本的なクラスで、文字列をトークンに分解するためのカスタマイズ可能なインターフェースを提供します。shlex を直接使用する代わりに、shlex クラスをインスタンス化して、より詳細な制御を行えます。
#### 利用例
引数の分割
```python
import shlex

# シェル風に文字列を分割
command_line = 'python script.py --option "some value"'
args = shlex.split(command_line)

print(args)  # 出力: ['python', 'script.py', '--option', 'some value']
```
この例では、`shlex.split()` を使用して、コマンドライン引数をリストに分割しています。ダブルクォートで囲まれた some value は1つの引数として正しく扱われます。

エスケープされた文字列
```python
import shlex

# エスケープされた文字列を処理
command_line = 'echo "Hello, World!"'
args = shlex.split(command_line)

print(args)  # 出力: ['echo', 'Hello, World!']
```
`shlex.quote()` を使った引数の安全なエスケープ
```python
import shlex

# コマンドライン引数を安全にエスケープ
command = "echo 'This is a test'"
safe_command = shlex.quote(command)

print(safe_command)  # 出力: "'echo 'This is a test''"
```
ここでは、`shlex.quote()` を使用して、引数をシェルで安全に使えるように適切にエスケープしています。

shlex.shlex クラスを使ったトークン化
```python
import shlex

# shlex クラスを使ってトークンを解析
lexer = shlex.shlex('python -m module --option value')
lexer.whitespace_split = True  # 空白で分割する設定

tokens = list(lexer)
print(tokens)  # 出力: ['python', '-m', 'module', '--option', 'value']
```
`shlex.shlex` クラスを使用すると、トークン解析の設定をカスタマイズできます。例えば、whitespace_split = True に設定することで、空白でトークンを分割することができます。



## 20. Tkを用いたGUIプログラミング
- ### 20-1 `tkinter` --- Tcl/Tkインターフェース
`tkinter` モジュールは、Tcl/Tk を利用した GUI アプリケーションを作成するためのツールを提供します。tkinter を使うことで、クロスプラットフォームで動作するデスクトップアプリケーションを簡単に作成することができます。主にウィジェットを使用して、ユーザーインターフェースを構築します。

#### 主な機能
- **`mainloop()`**: イベント処理ループを開始し、GUI を表示し続けます。
　　　　
- **`title(title)`**: ウィンドウのタイトルを設定します。
　　　　
- **` geometry(文字列型、'幅x高さ' の形式)`**: 
ウィンドウのサイズを設定します。
<br>
ウィジェットクラス:
    
- **`Button(text, command)`**: 
ボタンウィジェット。ユーザーがクリックできるボタンを作成します。
　　　　
- **`Label(text)`**: テキストを表示するためのラベルウィジェット。
　　　　
- **`Entry()`**: ユーザーがテキストを入力するためのエントリウィジェット。
　　　　
- **`Text()`**: 複数行のテキストを入力するためのウィジェット。
　　　　
- **`Canvas()`**: 描画領域を提供し、図形や画像の表示ができます。
　　　　　
- **`Frame()`**: 複数のウィジェットをグループ化するためのフレーム。
    　　　　
- **`pack()`**: ウィジェットを親ウィンドウに自動的に配置します。
 　　　　   
- **`grid()`**: ウィジェットを格子状に配置します。
　　　　    
- **`place()`**: ウィジェットを絶対位置に配置します。
#### 利用例
シンプルなウィンドウを作成
```python
import tkinter as tk

# メインウィンドウの作成
root = tk.Tk()

# ウィンドウタイトルの設定
root.title("Hello, Tkinter!")

# ウィンドウサイズの設定
root.geometry("300x200")

# メインループを開始
root.mainloop()
```
このコードは、`Tk()` を使ってメインウィンドウを作成し、タイトルとサイズを設定しています。その後、`mainloop()` を呼び出してウィンドウを表示し、ユーザーの操作を待ちます。

ボタンとイベントハンドリング
```python
import tkinter as tk

# ボタンクリック時の動作を定義
def on_button_click():
    print("Button clicked!")

# メインウィンドウの作成
root = tk.Tk()

# ボタンウィジェットの作成
button = tk.Button(root, text="Click Me", command=on_button_click)

# ボタンの配置
button.pack()

# ウィンドウを表示
root.mainloop()
```
ここでは、ボタンがクリックされたときに `on_button_click` 関数が呼ばれるように設定しています。ボタンがクリックされると、コンソールに「Button clicked!」と表示されます。

ラベルとエントリウィジェット
```python
import tkinter as tk

# メインウィンドウの作成
root = tk.Tk()

# ラベルウィジェットの作成
label = tk.Label(root, text="Enter your name:")
label.pack()

# エントリウィジェットの作成
entry = tk.Entry(root)
entry.pack()

# エントリの内容を取得する関数
def get_name():
    name = entry.get()
    print(f"Hello, {name}!")

# ボタンウィジェットの作成
button = tk.Button(root, text="Submit", command=get_name)
button.pack()

# ウィンドウを表示
root.mainloop()
```
このコードでは、ユーザーが名前を入力するためのエントリウィジェットを作成し、ボタンをクリックするとその内容を取得して表示します。

レイアウト管理
```python
import tkinter as tk

# メインウィンドウの作成
root = tk.Tk()

# ウィジェットの作成
label1 = tk.Label(root, text="Label 1")
label2 = tk.Label(root, text="Label 2")
button = tk.Button(root, text="Click Me")

# ウィジェットの配置
label1.grid(row=0, column=0)
label2.grid(row=1, column=0)
button.grid(row=2, column=0)

# ウィンドウを表示
root.mainloop()
```
ここでは、`grid()` レイアウトマネージャを使って、ウィジェットを行列形式で配置しています。


<br><br>
- ### 20-2 `tkinter.ttk` --- Tkテーマ付きウィジェット
`tkinter.ttk` モジュールは、Python の `tkinter` モジュールに追加された拡張で、より洗練された、テーマ対応のウィジェットを提供します。ttk（Themed Tkinter）ウィジェットは、従来の tkinter ウィジェットに比べて、プラットフォームごとに異なるテーマやスタイルをサポートし、より現代的な外観のアプリケーションを作成することができます。これにより、tkinter のウィジェットの外観が、より一貫性のあるものになります。

#### 主な機能
- **`ttk.Button(master)`**: テーマ付きのボタンウィジェット。
　　　　
- **`ttk.Label(master)`**: テーマ付きのラベルウィジェット。
　　　　
- **`ttk.Entry(master)`**: テーマ付きのエントリウィジェット（テキスト入力欄）。
　　　　
- **`ttk.Combobox(master, values)`**:
 テーマ付きのコンボボックスウィジェット（ドロップダウンリスト）。
　　　　
- **`ttk.Treeview(master)`**: ツリー状のデータを表示するウィジェット。
　　　　
- **`ttk.Progressbar(master, length)`**: プログレスバーウィジェット。
　　　　
- **`ttk.Style()`**: ウィジェットのスタイルを設定するためのクラス。
#### 利用例
ttk ウィジェットの基本的な使用例
```python
import tkinter as tk
from tkinter import ttk

# メインウィンドウの作成
root = tk.Tk()

# テーマ付きボタンの作成
button = ttk.Button(root, text="Click Me")
button.pack()

# メインループを開始
root.mainloop()
```
このコードでは、`ttk.Button` を使用して、テーマ付きのボタンを作成しています。ttk のボタンは、プラットフォームに応じたネイティブな外観を持ちます。

スタイルのカスタマイズ
```python
import tkinter as tk
from tkinter import ttk

# メインウィンドウの作成
root = tk.Tk()

# ttk スタイルオブジェクトを作成
style = ttk.Style()

# スタイルの設定
style.configure("TButton", font=("Helvetica", 12), foreground="blue", background="yellow")

# スタイルを適用したボタンの作成
button = ttk.Button(root, text="Styled Button", style="TButton")
button.pack()

# メインループを開始
root.mainloop()
```
この例では、`ttk.Style` を使用して、ボタンのフォントや色をカスタマイズしています。TButton スタイルを変更することで、ボタンの外観が変わります。

テーマの変更
```python
import tkinter as tk
from tkinter import ttk

# メインウィンドウの作成
root = tk.Tk()

# テーマの設定
style = ttk.Style()
style.theme_use('clam')  # 使用するテーマを指定 ('clam', 'alt', 'classic', 'vista', 'xpnative')

# テーマ付きのラベルの作成
label = ttk.Label(root, text="Hello, themed world!")
label.pack()

# メインループを開始
root.mainloop()
```
ここでは、`ttk.Style()`.`theme_use()` メソッドを使用して、`clam` テーマを適用しています。異なるテーマを使用することで、アプリケーションの外観を変更できます。

コンボボックスの使用例
```python
import tkinter as tk
from tkinter import ttk

# メインウィンドウの作成
root = tk.Tk()

# コンボボックスの作成
combo = ttk.Combobox(root, values=["Option 1", "Option 2", "Option 3"])
combo.pack()

# メインループを開始
root.mainloop()
```
ttk.Combobox を使用して、プラットフォームネイティブの外観を持つドロップダウンリストを作成しています。

プログレスバーの使用例
```python
import tkinter as tk
from tkinter import ttk
import time

# メインウィンドウの作成
root = tk.Tk()

# プログレスバーの作成
progress = ttk.Progressbar(root, length=200, mode='indeterminate')
progress.pack()

# プログレスバーを開始
progress.start()

# 一定時間待機（デモ用）
time.sleep(5)

# メインループを開始
root.mainloop()
```
`ttk.Progressbar` を使って、プログレスバーを作成し、`start()` メソッドで進行を開始します。`indeterminate` モードでは、進行状況が不確定であることを示すアニメーションが表示されます。


## 21. 開発ツール
- ### 21-1 `typing` --- 型ヒントサポート
`typing` モジュールは、型ヒントを使ってコードの可読性と保守性を高めるためのツールを提供します。型ヒントは、関数や変数の期待されるデータ型を明示的に記述することで、静的解析ツールやエディタの補完機能を活用でき、コードの品質を向上させることができます。Python は動的型付け言語ですが、`typing` を使用することで、コードの型に関する情報を明示的に提供することができます。

#### 主な機能

- **`Union[]`**: 2つ以上の型のいずれかであることを示す。
　　　　
- **`Optional`**: None を許容する型。
　　　　
- **`Any`**: 任意の型。型チェックを無効にする。
　　　　
- **`Callable[]`**: 関数の型を示す。
　　　　
- **`TypeVar()`**: 型パラメータを定義するためのジェネリック型。
#### 利用例
基本的な型ヒント
```python
def greet(name: str) -> str:
    return f"Hello, {name}!"

greeting = greet("Alice")
```

<br><br>
 - ### 21-2 `pydoc` --- ドキュメント生成とオンラインヘルプ
 `pydoc` モジュールは、Python のコードに対するドキュメントを生成したり、オンラインヘルプを提供したりするためのツールです。このモジュールを使用すると、Python モジュール、クラス、関数、メソッドのドキュメントを簡単に表示したり、HTML ドキュメントを生成することができます。`pydoc` を使用することで、Python の標準ライブラリや自作のモジュールに関するドキュメントをすばやく確認することができます。

#### 主な機能
- **`pydoc.help(obj)`**: 
引数に指定したオブジェクトやモジュールのドキュメントを表示します。
- **`pydoc.render_doc(obj)`**: 指定したオブジェクトに対するドキュメントを生成します。
　　　　
- **`pydoc.writedoc(module)`**: 
指定したモジュールに対するドキュメントをファイルに書き込みます。

- **`pydoc.locate(name)`**: モジュール名からモジュールの完全なパスを探します。
　　　　
- **`pydoc.pager(text)`**: 長いドキュメントをページャーで表示します。
#### 利用例
インタラクティブなヘルプ
Python シェル内で `help()` 関数を使うと、インタラクティブなヘルプシステムが利用できます。例えば、`math` モジュールについてのヘルプを表示するには次のようにします。

```python
import pydoc

# 'math' モジュールのドキュメントを表示
pydoc.help('math')
```
このコマンドを実行すると、`math` モジュールに関する詳細な情報が表示されます。モジュール内の関数やクラス、使い方が確認できます。


モジュールの HTML ドキュメントを生成
`pydoc` では、モジュールのドキュメントを HTML 形式で生成することもできます。例えば、`math` モジュールの HTML ドキュメントをファイルに出力するには次のようにします。

```bash
python -m pydoc -w math
```
出力例
```bash
Help on built-in module math:

NAME
    math

DESCRIPTION
    This module provides access to the mathematical functions
    defined by the C standard.
```
このコマンドを実行すると、math.html という名前の HTML ドキュメントがカレントディレクトリに作成されます。このファイルをブラウザで開くことで、`math` モジュールのドキュメントをグラフィカルに閲覧できます。

任意のオブジェクトのドキュメントを表示
`pydoc.render_doc()` を使って、任意のオブジェクトに対するドキュメントを生成することもできます。たとえば、Python の組み込み関数 `len()` に関するドキュメントを表示するには次のようにします。

```python
import pydoc

# 'len' 関数のドキュメントを生成
doc = pydoc.render_doc(len)
print(doc)
```

出力
```
Python Library Documentation: built-in function len in module builtins

lleenn(obj, /)
    Return the number of items in a container.
```
このコードを実行すると、`len()` 関数の詳細な説明がテキスト形式で表示されます。

オンラインヘルプを起動
`pydoc` モジュールを使用して、ローカルサーバーを立ち上げ、オンラインでヘルプを表示することもできます。次のコマンドを実行すると、ブラウザで Python のヘルプを表示することができます。

```bash
python -m pydoc -p 1234
```
これにより、ポート番号 1234 でヘルプサーバーが立ち上がり、ブラウザで http://localhost:1234 にアクセスすることで、Python の組み込みモジュールや関数に関するドキュメントをインタラクティブに閲覧できます。


<br><br>
- ### 21-3 `doctest` --- 対話型の例をテスト
`doctest` モジュールは、Python のドキュメント内に埋め込まれた対話型の例を自動的にテストするためのツールです。このモジュールを使用することで、ドキュメントに書かれたコードサンプルが実際に動作するかどうかを確認することができ、コードとドキュメントが一致しているかどうかを検証できます。これにより、ドキュメントが常に最新で正確な状態を保つことができます。

#### 主な機能
- **`doctest.testmod(mod)`**: 
モジュール内のドキュメントに記載されたテストを実行します。
　　　　
- **`doctest.testfile(filename)`**: 
指定したファイルのドキュメント内のテストを実行します。
　　　　
- **`doctest.run_docstring_examples(obj)`**: 
ドキュメント内の例を直接実行してテストします。
#### 利用例
モジュールのドキュメントテスト
`doctest.testmod()` を使用すると、モジュール内に埋め込まれた対話型の例を自動的にテストできます。以下は、モジュール内のドキュメントに記載された例をテストする例です。

```python
import doctest

def square(x):
    """
    Returns the square of a number.

    >>> square(2)
    4
    >>> square(3)
    9
    >>> square(-1)
    1
    """
    return x * x

# ドキュメント内の例をテスト
doctest.testmod()
```
上記のコードでは、`square` 関数のドキュメントに記載されたコード例が実際に実行され、結果が期待されるものと一致するかどうかがテストされます。もし結果が一致しなければ、エラーメッセージが表示されます。

ファイル内のテスト
`doctest.testfile()` を使って、Python ファイル内に書かれたドキュメントテストを実行することもできます。例えば、example.txt というテキストファイルに以下のようなコード例が含まれているとします。

example.txt:

```python
>>> 1 + 1
2
>>> 2 * 3
6
>>> len("hello")
5
```
このファイルのテストを実行するには、次のようにします。

```python
import doctest

# テキストファイル内のテストを実行
doctest.testfile('example.txt')
```
このコードを実行すると、example.txt 内のすべてのコードサンプルが実行され、期待される結果と一致するかどうかがテストされます。

結果のカスタマイズ
テスト結果をより詳細に確認したい場合は、`doctest` に verbose=True を設定することができます。これにより、テストの実行過程や結果が詳細に表示されます。

```python
import doctest

# 詳細なテスト結果を表示
doctest.testmod(verbose=True)
```

- ### 21-4 `unittest` --- ユニットテストフレームワーク
`unittest` モジュールは、ユニットテストフレームワークです。このモジュールは、単体テスト（ユニットテスト）の作成と実行をサポートしており、Python プログラムの各部分が正しく動作するかどうかを確認するために使用されます。unittest は、テストケースの実行、結果の集計、エラーメッセージの報告を自動化し、コードの品質を向上させるために広く使用されています。

#### 主な機能

- **`unittest.TestCase()`**: 
ユニットテストを作成するためのベースクラスです。このクラスを継承し、テストメソッドを定義します。
　　　　
- **`unittest.main()`**: 
スクリプトが直接実行された場合に、テストを実行するためのエントリーポイントです。
　　　　
- **`unittest.TestSuite()`**: 複数のテストケースをまとめて実行するためのクラスです。

#### 利用例
基本的なテストケース
unittest を使って、簡単なユニットテストを作成する例です。

```python
import unittest

# テスト対象の関数
def add(x, y):
    return x + y

# ユニットテストのクラス
class TestMathOperations(unittest.TestCase):

    def test_add(self):
        # add 関数が正しく動作するかテスト
        self.assertEqual(add(2, 3), 5)
        self.assertEqual(add(-1, 1), 0)
        self.assertEqual(add(0, 0), 0)

if __name__ == '__main__':
    unittest.main()
```
上記のコードでは、`add` 関数が期待通りに動作するかどうかを確認するためのテストメソッド test_add を定義しています。`assertEqual()` メソッドを使って、関数の出力が期待される値と一致することを確認しています。

セットアップとティアダウン
テストケースにおいて、テスト前に準備すべきデータがある場合や、テスト後にリソースを解放する必要がある場合、`setUp()` と `tearDown()` メソッドを使うことができます。

```python
import unittest

class TestExample(unittest.TestCase):

    def setUp(self):
        # 各テストメソッドの前に実行される
        self.test_data = [1, 2, 3, 4, 5]

    def test_sum(self):
        # setUpで準備したデータを使ったテスト
        self.assertEqual(sum(self.test_data), 15)

    def tearDown(self):
        # 各テストメソッドの後に実行される
        del self.test_data

if __name__ == '__main__':
    unittest.main()
```
`setUp()` メソッドは、各テストメソッドの実行前に呼び出され、`tearDown()` メソッドはテストメソッドの実行後に呼び出されます。これにより、テストメソッドが共通の初期データを使用することができ、後処理も自動的に行えます。

テストスイートの実行
複数のテストケースをまとめて実行するために、unittest.TestSuite を使用することができます。

```python
import unittest

class TestExample(unittest.TestCase):

    def test_addition(self):
        self.assertEqual(2 + 3, 5)

    def test_subtraction(self):
        self.assertEqual(5 - 3, 2)

# テストスイートの作成
suite = unittest.TestSuite()
suite.addTest(TestExample('test_addition'))
suite.addTest(TestExample('test_subtraction'))

# テストランナーで実行
runner = unittest.TextTestRunner()
runner.run(suite)
```
このコードでは、TestExample クラスの2つのテストメソッドをテストスイートに追加し、テストランナーで実行しています。


# おわりに
こうしてみると、標準ライブラリだけでも、すごい数ですね、、

(最後まで全て読んでくださった方がいるかは分かりませんが、)最後までお読みいただきありがとうございます！
　　　　　
何度も見直しはしたものの、表記間違いや、解説誤りがあるかも知れません。お気づきの方は優しくご指摘いただけますと幸いです。
　　　　　
皆様の勉強に少しでもお役に立てれば光栄です！


:::note info
弊社Nucoでは、他にも様々なお役立ち記事を公開しています。よかったら、Organizationのページも覗いてみてください。
また、Nucoでは一緒に働く仲間も募集しています！興味をお持ちいただける方は、[こちら](https://recruit.nuco.co.jp/?qiita_item_id=0873a5f286049ba46265)まで。
:::