第140回 実務で使えるPython基礎:標準ライブラリで作る生産性向上ツール

はじめに — つまずきに寄り添って

標準ライブラリだけで仕事に使えるツールを作ろうとすると、「依存を減らしたい」「でも本当に標準で足りるのか?」と迷うことが多いはずです。本記事ではその迷いに寄り添い、まずは標準ライブラリだけで安全に、保守しやすく、実用的な小さなツールを作る手順とテンプレートを示します。

導入:なぜまず標準ライブラリを使うか

標準ライブラリを優先する理由は主に次の3点です。

  • 依存管理が簡単(追加のパッケージ管理が不要)
  • 保守性が高い(長期的互換性やドキュメントが豊富)
  • セキュリティと信頼性(広くレビューされたコード群)

標準ライブラリで十分かを判断するチェックリスト

項目 標準で十分か? コメント
HTTPクライアント 限定的 簡単なGET/POSTはurllibで可能。認証やセッション管理が複雑ならrequestsの検討を。
CSV/JSON処理 十分 標準のcsv/jsonでほとんどの業務処理はこなせる。
データ解析(大規模) 不十分 大量データや高度な集計はpandasの方が現実的。
非同期IOや高スループット 場合による asyncioは強力だが、使いこなしコストを考慮。

まずは小さなPoCを標準ライブラリで作り、性能・可読性・開発コストを見てから外部依存を検討するのが実務的です。

ハンズオン:主要モジュールと短い実例コード

ここでは実務でよく使うモジュールを例とともに紹介します。各コードはそのまま貼って試せる最小例です。

モジュール 用途
pathlib ファイル/パス操作(プラットフォーム非依存)
logging + RotatingFileHandler ログ設計とローテーション
configparser / os.environ 設定管理(ファイル/環境変数)
csv / json 軽量データ入出力
itertools ストリーム処理(メモリ節約の変換)
collections defaultdict, Counter, deque などの便利構造
functools.lru_cache 簡易キャッシュ
subprocess 外部コマンド実行
tempfile / shutil 一時ファイルとアーカイブ

pathlib(パス操作)

from pathlib import Path
p = Path('data')
for f in p.glob('*.csv'):
    print(f.resolve())

logging + RotatingFileHandler(ログ設計)

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger('myapp')
handler = RotatingFileHandler('logs/app.log', maxBytes=10_000_00, backupCount=5)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

logger.info('start')

configparser / os.environ(設定管理)

import configparser
import os

config = configparser.ConfigParser()
config.read('config.ini')
api_key = os.environ.get('API_KEY') or config.get('default', 'api_key', fallback=None)

csv / json(軽量データ入出力)

import csv
import json

# CSV読み取り
with open('input.csv', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['id'], row['value'])

# JSON書き出し
with open('out.json', 'w', encoding='utf-8') as f:
    json.dump({'ok': True}, f, ensure_ascii=False, indent=2)

itertools(ストリーミング変換)

import itertools

def chunks(iterable, n):
    it = iter(iterable)
    while True:
        chunk = list(itertools.islice(it, n))
        if not chunk:
            break
        yield chunk

for c in chunks(range(10), 3):
    print(c)

collections(defaultdict / Counter / deque)

from collections import defaultdict, Counter, deque

cnt = Counter(['a','b','a'])
print(cnt.most_common())

d = defaultdict(list)
d['k'].append(1)

q = deque(maxlen=100)
q.append(1)

functools.lru_cache(キャッシュ)

from functools import lru_cache

@lru_cache(maxsize=128)
def expensive(x):
    # 重い計算や外部呼び出しの結果をキャッシュ
    return x * x

print(expensive(3))

subprocess(外部コマンド実行)

import subprocess

# 引数をリストで渡してシェルインジェクションを避ける
res = subprocess.run(['ls', '-la'], capture_output=True, text=True)
print(res.stdout)

tempfile / shutil(一時ファイルとアーカイブ)

import tempfile
import shutil
from pathlib import Path

with tempfile.TemporaryDirectory() as td:
    tmp = Path(td) / 'data.txt'
    tmp.write_text('hello')
    shutil.make_archive('archive', 'gztar', root_dir=td)

実務パターン:すぐ使えるテンプレート3本

ここではテンプレートごとに必要モジュール、設定例、ログ設定、最小テスト例を示します。

1) CLIバッチ用ユーティリティ(ファイル変換等)

  • 主なモジュール:argparse / pathlib / csv / logging / configparser
  • 設定ファイル例(config.ini):
[default]
input_dir = ./data
output_dir = ./out
log_file = ./logs/app.log
  • 簡易ログ設定:前述のRotatingFileHandlerを使う
  • 最小テスト(pytest)例:
def test_cli_process(tmp_path):
    # 入出力のダミーファイルを作って処理が期待通り動くかを確認
    in_file = tmp_path / 'input.csv'
    in_file.write_text('id,value\n1,100\n')
    # process_cliは実装関数
    process_cli(str(in_file), str(tmp_path / 'out'))
    assert (tmp_path / 'out' / 'input.csv').exists()

2) ファイル監視→処理の小型ワーカー

  • 主なモジュール:pathlib / time / logging / collections.deque / tempfile
  • 構成:監視ループで新着ファイルをキュー(deque)に入れ、ワーカーが順次処理
from collections import deque
from pathlib import Path
import time

queue = deque()
watch = Path('inbox')
while True:
    for f in watch.glob('*.csv'):
        queue.append(f)
        f.rename(f.with_suffix('.processing'))
    if queue:
        process(queue.popleft())
    time.sleep(5)
  • 設定は環境変数優先(os.environ)にして、config.iniはフォールバックとする
  • テスト:ファイルの到着と処理開始をモックまたは一時ディレクトリで確認

3) 日次アーカイブ+アップロードスクリプト

  • 主なモジュール:shutil / tempfile / subprocess / logging / datetime
  • 処理の流れ:古いファイルを集めて一時ディレクトリで圧縮→外部コマンド(curl/s3cli等)でアップロード→クリーンアップ
import shutil
from datetime import datetime
from pathlib import Path

src = Path('logs')
archive_name = f'logs-{datetime.today().date().isoformat()}'
shutil.make_archive(archive_name, 'gztar', root_dir=src)
# subprocessでアップロードコマンドを実行

既存ワークフローとの接続例

過去記事との連携例をテーブルで示します。

ステップ 該当記事 標準ライブラリでの実装例
CSV入出力 第134回 csv.DictReader → itertoolsでストリーム変換
CSV前処理 第135回 collections.Counterで簡易集計後、jsonで保存
推論API登録 第139回 subprocessやurllibでバッチ登録リクエスト

例:CSVクリーニング→itertoolsでストリーム処理→subprocessで外部ETL呼び出し→FastAPIにバッチ登録

import csv
import itertools
import subprocess
from urllib import request, parse

# 1. ストリームで読み、変換
with open('in.csv', newline='') as f:
    reader = csv.DictReader(f)
    cleaned = ({'id': r['id'], 'v': float(r['value'])} for r in reader if r['value'])
    # 2. バッチ処理(外部ETLを呼ぶ)
    for chunk in itertools.islice(cleaned, 1000):
        subprocess.run(['etl_tool', '--input', '-'], input=str(chunk).encode())
# 3. FastAPI に登録
data = parse.urlencode({'job': 'daily'}).encode()
req = request.Request('https://example/api/register', data=data)
request.urlopen(req)

運用チェックリスト

項目 確認ポイント
ログローテーション 適切なmaxBytes/backupCountが設定されているか
ログレベル運用 本番はINFO以上、デバッグ時にDEBUGを有効化する仕組み
例外ハンドリング リトライポリシーとアラート(最低限stdout/exit codeで監視可能に)
一時ファイルのクリーンアップ TemporaryDirectoryやtry/finallyで確実に削除
メトリクス出力 標準出力へ簡易メトリクス(処理数、エラー数)を出す

実装上の注意と落とし穴

  • subprocessの呼び出しは引数をリストで渡し、ユーザー入力を直接渡さない(シェルインジェクション対策)。
  • itertoolsでメモリ節約をしても、中間でlist化すると効果が消える。isliceやジェネレータを意識する。
  • loggingはモジュール間でグローバルに影響するため、テストではログ設定のリセットを行う。
  • 標準ライブラリで性能限界に達したら、代替ライブラリ導入の判断基準(処理時間、メモリ、開発コスト)を明確にする。

成果物と次の一歩

本記事で紹介したテンプレートはGitHub向けに最小リポジトリを用意すると実務導入が早まります。例:

ファイル/ディレクトリ 説明
README.md 導入手順と設定例
config.ini サンプル設定ファイル(ENV優先)
src/ スクリプト本体(__main__.py とモジュール)
tests/ pytest用の最小テスト
.github/workflows/ci.yml pytestを回すCI設定(例)

WordPressに貼りやすいコードブロック例(すでに本文中で複数提示)をそのままコピーして使ってください。

次回候補:itertools+collectionsの深掘り、標準ライブラリだけで作る小さなCLIアプリ公開フロー。

まとめ

標準ライブラリは、依存管理や保守性、セキュリティ面で強い利点があります。まず標準でプロトタイプを作り、実際の負荷や運用を見てから外部ライブラリ導入を判断するのが実務的です。本稿のテンプレートやチェックリストを使えば、すぐに試せるツールが用意できます。まずは小さく始めて、運用で得た知見を元に改善していきましょう。