(2022/05/28 追記)
よりスマートな方法、早速コメントいただきましてありがとうございます!
ぜひコメントまで含めて読んでいっていただけると幸いです!
はじめに
久々にpythonでcsv読み書きしてどうのこうのするプログラム書いてたら、
デバッグで実際データ入れたときに思うように動かんすぎてズッこけたので備忘録です。
エクセルで作ったcsvファイル(CSV UTF-8(コンマ区切り))を読み書きしようとしてオッ...となりました。
以下のような2行5列のデータが入ってるcsvファイルがあると思って以降のプログラム見てってください。
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
6 | 7 | 8 | 9 | 10 |
最初に私が書いたプログラムは以下です。
import csv
with open(filename) as f:
reader = csv.reader(f)
l = [row for row in reader]
print(l)
"""結果
[['\ufeff1', '2', '3', '4', '5'], ['6', '7', '8', '9', '10']]
""""
- 読み込んだら頭に'\ufeff'ついてて焦った
- そもそもcsv読み込みデフォルトは文字列読み込みだった
の二本立てです。
読み込んだら頭に'\ufeff'ついてて焦った
まず結果printしてみて、'\ufeff'...君誰!!!
実際にいろいろ書いて動かしてたプログラムでは、
[ invalid literal for int() with base 10: '\ufeff1' ]
ってエラーが出て止まってました。
int()に'\ufeff1'を入れようとしてしまってたために出たエラー。
'\ufeff'調べてみると、BOMというテキストの始まりを伝えるためのマークなんだそうです。
このBOMすっ飛ばして読み込めれば!ということなのですが、
これはエンコーディングを"utf-8-sig"に設定してあげればOKです。
import csv
with open(filename, encoding="utf-8-sig") as f:
reader = csv.reader(f)
l = [row for row in reader]
print(l)
"""結果
[['1', '2', '3', '4', '5'], ['6', '7', '8', '9', '10']]
""""
utf-8形式のファイルにはこのBOMがあるものとないものがあるんだそうでその辺も考慮必要そう。
参考:Python Tips: Python で UTF-8 の BOM ありなしを見分けたい
そもそもデフォルトは文字列読み込みだった
今まで数値のcsvファイルをimport csvして読み込んだことなかったのか、すっかり失念しておりました。
読み込み結果、文字列じゃん...
結果使うときにintとかfloatとかに適宜直してもいいんですが、今回の実装では以下の縛りがあったので
- 読み込み時にもうintやらfloatやらにしときたい
- できるだけ標準ライブラリのみでやりたい
読み込む型設定して読み込みできたらいいよねーってことで関数作ってみました。
import csv
def open_csv(filename,mode):
with open(filename,encoding="utf-8-sig") as f:
reader = csv.reader(f)
l = [row for row in reader]
if mode == "int":
l = [[int(y) for y in x ] for x in l]
elif mode == "float":
l = [[float(y) for y in x ] for x in l]
else:
pass
return l
arr = open_csv(filename,"str")
print(arr)
"""結果
[['1', '2', '3', '4', '5'], ['6', '7', '8', '9', '10']]
"""
arr = open_csv(filename,"int")
print(arr)
"""結果
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
"""
arr = open_csv(filename,"float")
print(arr)
"""結果
[[1.0, 2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0, 10.0]]
"""
いいかんじ!
さいごに
無限に知らないこと湧いて出てくるので最近逆に面白くなってきましたプログラミング
もっとスマートなやり方あればぜひ教えてください!