コンテンツにスキップ

Top

Python で CSV ファイルを操作する

Python を使ってcsvファイルの読み書きをする方法を述べる。

なお、ここでは NumPy や pandas は用いない。

環境は Ubuntu 18.04、Python 3.6.9 である。

最初に。やりがちなミス

ファイル名をcsv.pyにするな!

最初に言いますが、ありがち失敗ですが、これから作るPythonファイル名を csv.py にしてはいけません。

してしまうと、

import csv

が自身をインポートしようとして結果うまくいかなくなってしまいます。

結果、例えばcsv.writerを呼び出すと以下のようなエラーがでます。

AttributeError: module 'csv' has no attribute 'reader'
自作のcsv.pyにはreader()がいないので当然ですね!

別の名前にしましょう! (同じディレクトリにcsv.pyというファイルがあっても当然ダメなのでちゃんと消しましょう)

csvファイルの作成

まずはcsvファイルを作成しましょう。
writerow という関数で簡単に書けます。

csv_test.py

#!/usr/bin/env python3

import csv

def create_csv():
    with open('sample.csv', 'w') as f:
        w = csv.writer(f)
        w.writerow([0, 'aaa', 'あああ'])
        w.writerow([1, 'bbb', 'いいい'])
        w.writerow([2, 'ccc', 'ううう'])

if __name__ == '__main__':
    create_csv()

with を使っていますが勝手にファイルをcloseしてくれるので、ファイル操作時は with を積極的に用いましょう。

実行するとsample.csvができているはずです。

$ python3 csv_test.py
$ cat sample.csv
0,aaa,あああ
1,bbb,いいい
2,ccc,ううう

csvファイルの読み込み

・行の読み込み

#!/usr/bin/env python3

import csv 

def read_csv():
    with open('sample.csv', 'r') as f:
        r = csv.reader(f)
        for row in r:
            print(row)  

if __name__ == '__main__':
    read_csv()

これによりsample.csvを先頭から一行づつ読みます。

・行の各値の読み込み

行を読み込んだのは良いですが、各項目の値を読むにはどうしたらよいでしょうか?
単純にrow[0]やrow[1]のように配列番号で読めば良いだけです。

#!/usr/bin/env python3

import csv 

def read_csv():
    with open('sample.csv', 'r') as f:
        r = csv.reader(f)
        for row in r:
            print("{} {} {}".format(row[0], row[1], row[2]))

if __name__ == '__main__':
    read_csv()

・タイトルラベルの読み飛ばし

csvファイルにタイトル行がある場合を読み飛ばしたいと思います。 要望が多いのでしょう、1行読み飛ばす next() という関数が用意されています。
(むろん先頭だけじゃなく2回呼べば2行読み飛ばします)

まぁforループ内で最初の1行目読み飛ばせばいいだけなのですが、頻度の高い処理なのできっとだれかが関数化したのでしょう。

#!/usr/bin/env python3

import csv

def read_csv():
    with open('sample2.csv', 'r') as f:
        r = csv.reader(f)
        next(r)
        for row in r:
            print(row)

if __name__ == '__main__':
    read_csv()

csvファイルの書き込み

・行の追加

作成時にすでに書いていますが、csv.writer() で writerow()すれば良いです。

・行の削除

良い方法は何かあるんでしょうけど、基本作り直しです。10行目を消したいなら、10行目を読み飛ばした結果をcsvファイルとして出力することにより結果として削除する、という方法です。

・値の変更

各行の各列の値を直接変更出来たら楽なのですが標準のAPIでは存在していません。
ので、行レベルでの書き換えになるでしょう。しかしながら行の挿入もできませんのでやはりcsvファイルを最初から作り直しです。
大きなcsvファイルをcsvの標準機能で扱うのはちょっと面倒な気がしました。NumPyやpandasは便利なのがあるのでしょうけど。

以上!