acokikoy's notes

最近気になる=[NoCode, Shopify], I am..=[Python, ウクレレ, マニュアル車, CMS] LoveなWebディレクター

Python テキストファイルやcsvファイル R/Wの覚え書き (pathlib, csvライブラリ)

テキストファイルの文字コード判定や、csvファイル R/Wの覚え書き (pathlib, csvライブラリ)

ファイルを開く pathlib利用

from pathlib import Path

pth = Path('./SampleFiles/customers.csv')

# エンコードを指定してファイルオープン
with pth.open(encoding="utf-8") as f:
    contents = f.read()

print(contents)
"""
氏名,郵便番号,都道府県,,,
赤松雅康,737-0834,広島県,呉市,瀬戸見町,1-10
黒田徹子,697-0054,島根県,浜田市,高田町,1-5
鶴岡希実,103-0011,東京都,中央区,日本橋大伝馬町,3-6
比嘉沙良,939-1313,富山県,砺波市,柳瀬,4-13-1
河原希,294-0301,千葉県,館山市,香,8-13
秋本美希,629-1273,京都府,綾部市,下原町,4-15
森下誠一郎,289-1605,千葉県,山武郡芝山町,大台,3-14-5
丸山真奈美,399-0722,長野県,塩尻市,柿沢,7-16
...
"""

ファイルの文字コードが不明の時 - 文字コードを調べて、ファイルを読む

chardet ライブラリを利用する。

インストール

pip install chardet

インストールすると、コマンドラインからも利用できるようになる

% chardetect ./SampleFiles/customers.csv
./SampleFiles/customers.csv: utf-8 with confidence 0.99

使い方

from pathlib import Path
import chardet

pth = Path('./SampleFiles/customers.csv')

# バイナリで読み込み、detectメソッドで判定
with pth.open(mode='rb') as f:
    raw = f.read()
 encoding = chardet.detect(raw)['encoding']

    # chardet.detect(raw) が返すのはこんな値
    #  {
    #      'encoding': 'utf-8',
    #      'confidence': 0.99,
    #      'language': ''
    #   }


# 文字コードがわかったので改めて読み込み
with pth.open(encoding=encoding) as f:
    contents = f.read()

# あるいは、さっきのバイナリデータを変換
print(raw.decode(encoding))
"""
氏名,郵便番号,都道府県,,,
赤松雅康,737-0834,広島県,呉市,瀬戸見町,1-10
黒田徹子,697-0054,島根県,浜田市,高田町,1-5
鶴岡希実,103-0011,東京都,中央区,日本橋大伝馬町,3-6
比嘉沙良,939-1313,富山県,砺波市,柳瀬,4-13-1
河原希,294-0301,千葉県,館山市,香,8-13
秋本美希,629-1273,京都府,綾部市,下原町,4-15
森下誠一郎,289-1605,千葉県,山武郡芝山町,大台,3-14-5
丸山真奈美,399-0722,長野県,塩尻市,柿沢,7-16
...
"""

関数化しておく
ただし、いったん全部読みこむので、対象ファイルがデカいと効率悪いかも。

from pathlib import Path
import chardet

def det_encoding(path):
    # 文字コード判定 """
    with pth.open(mode='rb') as f:
        raw = f.read()
        return chardet.detect(raw)['encoding']

# 使い方
pth = Path('./SampleFiles/customers.csv')
encoding = det_encoding(pth)

csvファイルの読み書き

# ex2_customers_filter.py
import csv
from pathlib import Path

import chardet

# 文字コードを判定して返す
def det_encoding(path):
    with pth.open(mode='rb') as f:
        raw = f.read()
    return chardet.detect(raw)['encoding']


# メイン処理ここから
if __name__ == "__main__":
    pth = Path('./SampleFiles/customers.csv')
    encoding = det_encoding(pth)

    # csvファイル読み込み
    with pth.open(encoding=encoding) as f:
        reader = csv.reader(f)    # csv用のリーダー

        #  [['氏名', '郵便番号', '都道府県', '', '', '']] 関東在住メンバーだけ抽出
        KANTO = ("東京都", "神奈川県", "埼玉県", "千葉県", "茨城県", "群馬県", "栃木県")
        data_kanto = [row for row in reader if reader.line_num >2 if row[2] in KANTO]

    # csvファイルに書き出す
    pth_dst = Path('./customers_kanto.csv')
    with pth_dst.open(mode="w", encoding="utf-8", newline="") as f_dst:
        writer = csv.writer(f_dst)   # csv用のライター

        for data in data_kanto:
            writer.writerow(data)  # 1行分書き込み(リストorタプル型で渡す)

補足: reader.line_num で行番号が取れる

with pth.open(encoding='utf-8') as f:
    reader = csv.reader(f)

    for row in reader:
        print(f'{reader.line_num}: {row}')
    """
    1: ['氏名', '郵便番号', '住所', '', '', '']
    2: ['赤松雅康', '737-0834', '広島県', '呉市', '瀬戸見町', '1-10']
    3: ['黒田徹子', '697-0054', '島根県', '浜田市', '高田町', '1-5']
    4: ['鶴岡希実', '103-0011', '東京都', '中央区', '日本橋大伝馬町', '3-6']
    5: ['比嘉沙良', '939-1313', '富山県', '砺波市', '柳瀬', '4-13-1']
    6: ['河原希', '294-0301', '千葉県', '館山市', '香', '8-13']
    7: ['秋本美希', '629-1273', '京都府', '綾部市', '下原町', '4-15']
    ...
    """