はじめに
文字コードってさ、難しいよね
で、いろいろググっても概ね「頑張れ!」と言われているだけのような気がするので力技でどうにかしたお話をしようと思います。
きっかけ
私、友人が主催している自転車の大会の運営のお手伝いをしてます。
毎月開催というふざけた開催頻度なんですが、ほぼほぼ毎月お手伝い。その中で課題が上がってきたのが、外注している「大会エントリの情報整理が大変」だということ、そして個人情報を含むので外部に出せないのだと。
で、「プログラムでどうにかしてよ!」とのご依頼。
マクロでできるじゃん!
その通り、でもこの友人はエクセルを持っていない!w
そしてpandasでプログラムを書いてみたら、外注先から送られてくるcsvファイルの文字コードがちょくちょく変わるんですよ。業者の問題なのか、この友人の問題なのか・・・。
やりたいこと
csvを読み込む。
文字コードは不明(ちょくちょく変わる。)
これだけ
環境
2020 MacBook Air M1
pythonは3.10.8
pandasは2.0.1
考えたり、トライしたこと
まず考えたのが、実行できたらOK、ダメなら次の文字コードを試すということ
例えば、こんな感じ
for i in ['a','c','a','4','e',]:
print(float(i))
これだと、「a」はstr型なのでフロートに変換できずに終わります。
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[1], line 2
1 for i in ['a','c','a','4','e',]:
----> 2 print(float(i))
ValueError: could not convert string to float: 'a'
なので、try、except文を使いましょう。
for i in ['a','c','a','4','e',]:
try:
print(float(i))
except:
print(f'変換できへんかった: {i}')
でもね、最後まで行っちゃうと困っちゃう
変換できへんかった: a
変換できへんかった: c
変換できへんかった: a
4.0
変換できへんかった: e
読めた文字コードで終わりたいので、変換できた「4.0」で終わりたい。
ということで、for文にbreak
を追加。
正直、for文でbreak
できることを完璧に忘れてました。 <-- 今回、qiitaを描きたくなたモチベはここ。
for i in ['a','c','a','4','e',]:
try:
print(float(i))
break
except:
print(f'変換できへんかった: {i}')
出力はこちら
変換できへんかった: a
変換できへんかった: c
変換できへんかった: a
4.0
実施したこと
ということでこんな風にプログラムを修正してみた。
encoding_types = ['cp932', 'utf-8', 'utf_8_sig']
# 文字コード対策
for code in encoding_types:
try:
sports_entry_df = pd.read_csv(input_file, usecols=cols, encoding=code)
print(f'エンコードのタイプは「{code}」です')
break
except:
print(f'エンコードタイプ「{code}」では読み取れませんでした。')
どうやらこれで回避できたっぽい。友人からは連絡はまだない。
困ったら連絡くれるでしょ。
まとめ
for文とtry&except文を使って、力技で回避しました。
そして、for文からbreak
できることを思いだしました。w
さまざまな文字コードへの対応はあまり記述されていなくて困っている方も多いと思います。もっといい方法があれば教えていただけると嬉しいです。これマジで切実。
会社でも機種依存文字と半角カタカナで打ちのめされています。w
最後まで読んでいただきありがとうございます。
後日談
zennにいい投稿がありました!
力技でやっている僕が恥ずかしくなるほど素晴らしい記事!!