Pythonライブラリ Humanize 徹底解説:データを人に優しく! 🤝

Python

数値、日付、ファイルサイズなどを、もっと自然で読みやすい形式に変換しましょう。

1. Humanizeライブラリとは? 🤔

Humanizeは、Pythonで数値や日付、ファイルサイズなどを人間にとって読みやすい(”human-friendly”)形式に変換するためのライブラリです。コンピュータは生のデータを扱うのが得意ですが、私たち人間にとっては、例えば `1234567` という数字よりも `1,234,567` の方が、あるいは `2023-10-27 10:30:00` というタイムスタンプよりも「3分前」の方が直感的に理解しやすい場合があります。Humanizeは、このようなギャップを埋め、データ表現をより自然で分かりやすくする手助けをしてくれます。

特に、ユーザーインターフェースやレポート作成など、情報を分かりやすく伝える必要がある場面で非常に役立ちます。複雑なフォーマット処理を自分で実装する手間を省き、コードをよりシンプルに保つことができます。👍

主な機能:
  • 数値のフォーマット(カンマ区切り、単語表現、序数など)
  • 日付・時刻の相対的な表現(「昨日」「3分前」など)
  • ファイルサイズの分かりやすい表現(KB, MB, GBなど)
  • 国際化(i18n)対応で多言語での表示が可能

2. インストール方法 💻

Humanizeライブラリのインストールは、Pythonのパッケージマネージャーである pip を使って簡単に行えます。ターミナルまたはコマンドプロンプトで以下のコマンドを実行してください。

pip install humanize

インストールが完了したら、Pythonインタプリタやスクリプトで `import humanize` と記述してライブラリをインポートし、利用を開始できます。

import humanize
import datetime as dt

# バージョン確認 (任意)
# print(humanize.__version__)

3. 数値の人間化 🔢

Humanizeは数値をより人間が理解しやすい形に変換するための便利な関数を複数提供しています。

3.1. intcomma(value)

整数または浮動小数点数を3桁ごとのカンマ区切り文字列に変換します。大きな数値を読みやすくするのに非常に便利です。

import humanize

print(humanize.intcomma(12345))
print(humanize.intcomma(1234567.89))
print(humanize.intcomma("1234567")) # 文字列も受け付けます

出力:

12,345
1,234,567.89
1,234,567

国際化(後述)を有効にすると、ロケールに応じた区切り文字(例:ドイツ語ではピリオド)が使用されます。

3.2. intword(value, format='%.1f')

大きな数値を「12.3 million」や「1.5 billion」のような単語を使った簡潔な形式に変換します。特に非常に大きな数値を扱う際に有効です。

import humanize

print(humanize.intword(123455913))
print(humanize.intword(12345591313))
print(humanize.intword(1000000))
print(humanize.intword(10**100)) # googol (グーゴル) まで対応

出力:

123.5 million
12.3 billion
1.0 million
100.0 googol

`format` 引数で小数点以下の表示形式を指定できます(デフォルトは `’%.1f’`)。国際化を有効にすると、ロケールに応じた単語(例:ドイツ語の Millionen, Milliarden)が使用されます。

3.3. apnumber(value)

1から9までの数値を英単語(”one”, “two”, … “nine”)に変換します。10以上の数値はそのまま文字列として返されます。AP通信(Associated Press)のスタイルガイドに従っています。

import humanize

print(humanize.apnumber(1))
print(humanize.apnumber(5))
print(humanize.apnumber(10))

出力:

one
five
10

3.4. ordinal(value)

整数を序数(”1st”, “2nd”, “3rd”, “4th”など)の文字列に変換します。

import humanize

print(humanize.ordinal(1))
print(humanize.ordinal(2))
print(humanize.ordinal(3))
print(humanize.ordinal(11))
print(humanize.ordinal(21))
print(humanize.ordinal(103))

出力:

1st
2nd
3rd
11th
21st
103rd

3.5. fractional(value)

浮動小数点数を一般的な分数表現(”1/3″, “1/2” など)に変換します。適切な分数が見つからない場合は、元の数値を文字列として返します。

import humanize

print(humanize.fractional(1/3))
print(humanize.fractional(0.5))
print(humanize.fractional(5/4))
print(humanize.fractional(0.7)) # 近似する分数がない場合

出力:

1/3
1/2
1 1/4
0.7

数値関数まとめ

関数説明例 (入力 → 出力)
intcomma(value)数値をカンマ区切りにする1234567'1,234,567'
intword(value)数値を単語表現 (million, billion) にする1230000000'1.2 billion'
apnumber(value)1-9の数値を単語にする (APスタイル)3'three', 10'10'
ordinal(value)数値を序数にする2'2nd', 11'11th'
fractional(value)浮動小数点数を分数表現にする0.25'1/4'

Humanizeは、日付や時刻、経過時間をより自然な言葉で表現するための関数も提供しています。

4.1. naturalday(value, format='%b %d')

`datetime.date` または `datetime.datetime` オブジェクトを受け取り、今日、明日、昨日に該当する場合はそれぞれ “today”, “tomorrow”, “yesterday” を返します。それ以外の場合は、指定されたフォーマット(デフォルトは `’月 日’`、例: ‘Oct 27’)で日付を返します。

import humanize
import datetime as dt

today = dt.date.today()
yesterday = today - dt.timedelta(days=1)
tomorrow = today + dt.timedelta(days=1)
two_days_ago = today - dt.timedelta(days=2)

print(f"今日: {humanize.naturalday(today)}")
print(f"昨日: {humanize.naturalday(yesterday)}")
print(f"明日: {humanize.naturalday(tomorrow)}")
print(f"一昨日: {humanize.naturalday(two_days_ago)}")
print(f"一昨日 (フォーマット指定): {humanize.naturalday(two_days_ago, format='%Y-%m-%d')}")

出力 (実行日によって変わります):

今日: today
昨日: yesterday
明日: tomorrow
一昨日: Apr 03
一昨日 (フォーマット指定): 2025-04-03

4.2. naturaldate(value)

`naturalday` に似ていますが、今日、明日、昨日に該当しない場合は、年の情報も含めた形式(例: ‘Oct 27 2023’)で日付を返します。

import humanize
import datetime as dt

specific_date = dt.date(2023, 10, 27)
print(humanize.naturaldate(specific_date))

出力:

Oct 27 2023

4.3. naturaltime(value, future=False, months=True, minimum_unit="seconds", when=None)

`datetime.datetime` または `datetime.timedelta` オブジェクトを受け取り、現在時刻 (`when`で指定された時刻) からの相対的な時間を「〜前」や「〜後」といった自然な言葉で返します。

  • `value`: 比較対象の `datetime` または経過時間を表す `timedelta`。
  • `future`: `value`が `datetime` の場合、未来の時刻に対する表現を使うか (例: “in 5 minutes” vs “5 minutes ago”)。デフォルトは `False`。
  • `months`: 月単位や年単位での差分計算を有効にするか。デフォルトは `True`。
  • `minimum_unit`: 表示する最小単位 (“years”, “months”, “days”, “hours”, “minutes”, “seconds”)。デフォルトは `”seconds”`。これより小さい単位は切り捨てられます。
  • `when`: 相対時間の基準となる日時。デフォルトは現在時刻 (`datetime.datetime.now(tz=datetime.timezone.utc)` または `datetime.datetime.utcnow()`)。
import humanize
import datetime as dt

now = dt.datetime.now(tz=dt.timezone.utc) # タイムゾーン対応推奨

past_time = now - dt.timedelta(seconds=30)
future_time = now + dt.timedelta(hours=2, minutes=15)
long_ago = now - dt.timedelta(days=700)
time_delta = dt.timedelta(minutes=5)

print(f"30秒前: {humanize.naturaltime(past_time)}")
# valueがdatetimeの場合、デフォルトは過去として扱われる
print(f"2時間15分後: {humanize.naturaltime(future_time)}")
# future=True を使う場合
print(f"2時間15分後 (future=True): {humanize.naturaltime(now - dt.timedelta(hours=2, minutes=15), future=True)}")

print(f"700日前: {humanize.naturaltime(long_ago)}")
print(f"700日前 (月単位無効): {humanize.naturaltime(long_ago, months=False)}")
print(f"5分間の差: {humanize.naturaltime(time_delta)}")
print(f"5分間の差 (最小単位: hours): {humanize.naturaltime(time_delta, minimum_unit='hours')}")

# timedelta の利用例
delta_seconds = dt.timedelta(seconds=3)
print(humanize.naturaltime(delta_seconds)) # "3 seconds ago" (デフォルトは過去)
print(humanize.naturaltime(delta_seconds, future=True)) # "3 seconds from now"

delta_days = dt.timedelta(days=1.5)
print(humanize.naturaltime(delta_days)) # "a day ago"
print(humanize.naturaltime(delta_days, minimum_unit="hours")) # "36 hours ago"

出力 (実行時刻によって変わります):

30秒前: 30 seconds ago
2時間15分後: 2 hours ago
2時間15分後 (future=True): 2 hours from now
700日前: a year ago
700日前 (月単位無効): 700 days ago
5分間の差: 5 minutes ago
5分間の差 (最小単位: hours): now
3 seconds ago
3 seconds from now
a day ago
36 hours ago

naturaltime は非常に柔軟性が高く、ユーザーに時間の経過を分かりやすく伝えるのに最適です。

4.4. precisedelta(d, minimum_unit="seconds", suppress=(), format="%0.2f")

`timedelta` オブジェクトを受け取り、より詳細な時間差を人間が読みやすい形式で返します。例えば、「2 days, 3 hours, 5 minutes and 10 seconds」のように表現します。

  • `d`: `datetime.timedelta` オブジェクト。
  • `minimum_unit`: 表示する最小単位 (“seconds”, “minutes”, “hours”, “days”, “months”, “years”)。デフォルトは `”seconds”`。
  • `suppress`: 表示を抑制する単位のタプル (例: `(“seconds”,)` とすると秒は表示されない)。
  • `format`: 最小単位が秒の場合のフォーマット文字列。デフォルトは `”%0.2f”`。
import humanize
import datetime as dt

delta1 = dt.timedelta(days=2, hours=3, minutes=5, seconds=10.5)
delta2 = dt.timedelta(weeks=5, days=2, minutes=30)
delta3 = dt.timedelta(seconds=12345)

print(humanize.precisedelta(delta1))
print(humanize.precisedelta(delta1, minimum_unit="minutes"))
print(humanize.precisedelta(delta1, suppress=("minutes",)))
print(humanize.precisedelta(delta2))
print(humanize.precisedelta(delta3))

出力:

2 days, 3 hours, 5 minutes and 10.50 seconds
2 days, 3 hours and 5 minutes
2 days, 3 hours and 10.50 seconds
5 weeks, 2 days and 30 minutes
3 hours, 25 minutes and 45.00 seconds

`precisedelta` は、より正確な時間差を示したい場合に有用です。

5. ファイルサイズの人間化 💾

コンピュータが扱うバイト単位のファイルサイズは、人間にとっては直感的ではありません。Humanizeはこれを解決します。

5.1. naturalsize(value, binary=False, gnu=False, format='%.1f')

バイト数を入力として受け取り、”10 kB”、”4.1 MB”、”2.5 GiB” のような人間が読みやすいファイルサイズ文字列に変換します。

  • `value`: バイト単位のファイルサイズ (整数または浮動小数点数)。
  • `binary`: `True` の場合、2進接頭辞 (KiB, MiB, GiB など、1024ベース) を使用します。`False` (デフォルト) の場合、10進接頭辞 (kB, MB, GB など、1000ベース) を使用します。
  • `gnu`: `True` の場合、GNU `ls -h` スタイル(例: ‘1.0K’, ‘4.1M’)で出力します。`binary=True` も暗黙的に設定されます。
  • `format`: 数値部分のフォーマット文字列。デフォルトは `’%.1f’` (小数点以下1桁)。
import humanize

print(f"1000 bytes (Decimal): {humanize.naturalsize(1000)}")
print(f"1024 bytes (Decimal): {humanize.naturalsize(1024)}")
print(f"1024 bytes (Binary): {humanize.naturalsize(1024, binary=True)}")
print(f"1000000 bytes (Decimal): {humanize.naturalsize(1000000)}")
print(f"1048576 bytes (Decimal): {humanize.naturalsize(1048576)}")
print(f"1048576 bytes (Binary): {humanize.naturalsize(1048576, binary=True)}")
print(f"1048576 bytes (GNU): {humanize.naturalsize(1048576, gnu=True)}")
print(f"2500000000 bytes (Decimal): {humanize.naturalsize(2500000000)}")
print(f"2500000000 bytes (Binary): {humanize.naturalsize(2500000000, binary=True)}")
print(f"2500000000 bytes (Decimal, format='%.2f'): {humanize.naturalsize(2500000000, format='%.2f')}")

出力:

1000 bytes (Decimal): 1.0 kB
1024 bytes (Decimal): 1.0 kB
1024 bytes (Binary): 1.0 KiB
1000000 bytes (Decimal): 1.0 MB
1048576 bytes (Decimal): 1.0 MB
1048576 bytes (Binary): 1.0 MiB
1048576 bytes (GNU): 1.0M
2500000000 bytes (Decimal): 2.5 GB
2500000000 bytes (Binary): 2.3 GiB
2500000000 bytes (Decimal, format='%.2f'): 2.50 GB
注意: 10進接頭辞 (kB, MB, GB) と2進接頭辞 (KiB, MiB, GiB) の違いに注意してください。ファイルシステムやOSによっては表示される単位が異なる場合があります。`binary=True` は IEC 規格、`binary=False` (デフォルト) は SI 規格に基づいた表現です。

6. 国際化 (i18n) 対応 🌍

Humanizeは国際化に対応しており、様々な言語で人間化された文字列を出力できます。対応言語はライブラリのバージョンによって異なりますが、主要な言語の多くをサポートしています(例: フランス語、ドイツ語、スペイン語、ロシア語、日本語など)。

国際化機能を利用するには、まず `humanize.i18n.activate(locale, path=None)` 関数でロケール(言語設定)を有効にする必要があります。

  • `locale`: ロケール文字列 (例: ‘ja_JP’, ‘fr_FR’, ‘es’)。
  • `path`: 翻訳ファイル (.mo) が格納されているディレクトリのパス (オプション)。指定しない場合、Humanizeライブラリに同梱されている翻訳が使用されます。

ロケールを有効にすると、以降のhumanize関数の呼び出しは、その言語設定に基づいて行われます。元の言語(通常は英語)に戻すには `humanize.i18n.deactivate()` を呼び出します。

import humanize
import datetime as dt

# --- フランス語の例 ---
try:
    humanize.i18n.activate('fr_FR')
    print("--- Français ---")
    print(f"数値 (カンマ): {humanize.intcomma(12345.67)}") # フランス語では通常スペース区切り
    print(f"数値 (単語): {humanize.intword(1230000000)}")
    print(f"序数: {humanize.ordinal(1)}") # フランス語では '1er' など
    now = dt.datetime.now(tz=dt.timezone.utc)
    three_minutes_ago = now - dt.timedelta(minutes=3)
    print(f"時刻: {humanize.naturaltime(three_minutes_ago)}")
    print(f"ファイルサイズ: {humanize.naturalsize(1048576, binary=True)}") # 単位名も翻訳される場合がある
except FileNotFoundError:
    print("フランス語の翻訳ファイルが見つかりません。")


# --- スペイン語の例 ---
try:
    humanize.i18n.activate('es')
    print("\n--- Español ---")
    print(f"数値 (カンマ): {humanize.intcomma(12345.67)}") # スペイン語では通常ピリオド区切り
    print(f"数値 (単語): {humanize.intword(1230000000)}") # 'millardo' など
    print(f"序数: {humanize.ordinal(3)}") # スペイン語では '3º' など
    print(f"日付: {humanize.naturalday(dt.date.today() - dt.timedelta(days=1))}") # 'ayer'
except FileNotFoundError:
    print("スペイン語の翻訳ファイルが見つかりません。")

# --- 日本語の例 (一部対応) ---
try:
    humanize.i18n.activate('ja_JP')
    print("\n--- 日本語 ---")
    # 注意: 日本語の翻訳は限定的な場合があります
    print(f"数値 (カンマ): {humanize.intcomma(1234567)}") # 日本語ではカンマが一般的
    print(f"数値 (単語): {humanize.intword(1230000000)}") # '12.3億' のような翻訳が期待されるが、英語のままの場合もある
    now = dt.datetime.now(tz=dt.timezone.utc)
    five_seconds_ago = now - dt.timedelta(seconds=5)
    print(f"時刻: {humanize.naturaltime(five_seconds_ago)}") # '5秒前'
    print(f"ファイルサイズ: {humanize.naturalsize(1000000)}") # '1.0 MB' (単位は英語のままが多い)
except FileNotFoundError:
    print("日本語の翻訳ファイルが見つかりません。")
finally:
    # デフォルト(英語)に戻す
    humanize.i18n.deactivate()
    print("\n--- English (Default) ---")
    print(f"Time: {humanize.naturaltime(dt.datetime.now(tz=dt.timezone.utc) - dt.timedelta(seconds=5))}")

出力例 (翻訳ファイルの有無やバージョンにより変動):

--- Français ---
数値 (カンマ): 12 345,67
数値 (単語): 1,2 milliard
序数: 1er
時刻: il y a 3 minutes
ファイルサイズ: 1,0 Mio

--- Español ---
数値 (カンマ): 12.345,67
数値 (単語): 1,2 millardo
序数: 3º
日付: ayer

--- 日本語 ---
数値 (カンマ): 1,234,567
数値 (単語): 1.2 billion
時刻: 5秒前
ファイルサイズ: 1.0 MB

--- English (Default) ---
Time: 5 seconds ago
ポイント:
  • 利用可能なロケールと翻訳の完全性は、Humanizeのバージョンや環境によって異なります。
  • 特定のロケールが見つからない場合、`FileNotFoundError` が発生することがあります。
  • 独自の翻訳ファイルを作成して `path` 引数で指定することも可能です。

7. 応用例・ユースケース ✨

Humanizeライブラリは、様々な場面でコードの可読性とユーザー体験を向上させます。

  • Webアプリケーションのテンプレートエンジン (Django, Flask, Jinja2など): ユーザーに表示する最終更新日時 (`naturaltime`) やファイルサイズ (`naturalsize`)、コメント数 (`intcomma`) などを分かりやすく表示できます。Djangoには `django.contrib.humanize` として組み込まれており、テンプレートフィルタとして簡単に利用できます。
    {% load humanize %}
    
              

    最終更新: {{ post.updated_at|naturaltime }}

    添付ファイルサイズ: {{ attachment.size|naturalsize }}

    閲覧数: {{ post.views|intcomma }} 回

  • コマンドラインツール: 処理にかかった時間 (`precisedelta`) や処理したファイルの数 (`intcomma`)、ディスク使用量 (`naturalsize`) などをユーザーフレンドリーに表示します。
    import humanize
    import time
    import os
    
    start_time = time.monotonic()
    # ... 何らかの処理 ...
    processed_files = 15000
    total_size = 5 * 1024 * 1024 * 1024 # 5 GiB
    end_time = time.monotonic()
    duration = dt.timedelta(seconds=end_time - start_time)
    
    print(f"処理完了! ✨")
    print(f"処理ファイル数: {humanize.intcomma(processed_files)} 件")
    print(f"合計サイズ: {humanize.naturalsize(total_size, binary=True)}")
    print(f"処理時間: {humanize.precisedelta(duration)}")
  • データ分析・可視化レポート: Jupyter Notebookやレポート生成ツールで、大きな数値 (`intword`) や期間 (`naturaldelta`, `precisedelta`) を簡潔に表示し、レポートの読みやすさを向上させます。
  • ログメッセージ: ログに記録される経過時間やデータ量を、後で人間が確認しやすい形式で出力します。

8. まとめ 🎉

PythonのHumanizeライブラリは、数値、日付、時刻、ファイルサイズなどのデータを、人間にとって自然で理解しやすい形式に変換するための強力で使いやすいツールです。

  • intcomma, intword, apnumber, ordinal などで数値を分かりやすく。
  • naturalday, naturaltime, precisedelta などで日付や時間差を自然な言葉で表現。
  • naturalsize でファイルサイズを kB, MB, GiB などに変換。
  • 国際化対応により、多言語での表示が可能。

これらの機能を活用することで、アプリケーションのユーザーインターフェースを改善したり、レポートやログの可読性を高めたりすることができます。データと人間の間のコミュニケーションを円滑にするために、ぜひHumanizeライブラリをプロジェクトに取り入れてみてください!😄

コメント

タイトルとURLをコピーしました