1
0

More than 1 year has passed since last update.

【Python】エラー「_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)」と対処法

Posted at

概要

PythonでCSVを読むコードを実装していたら以下のエラーになりました。
本記事では原因と解決方法を記載します。

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

原因

発生する原因は、csvモジュールのreaderオブジェクトに対して、バイト列を返してしまっているため。
文字列を返す必要があります。以下、どちらでも上述のエラーになります。

csvfile = request.FILES['file']
reader = csv.DictReader(csvfile)
for row in reader:
csvfile = request.FILES['file']
decoded_file = csvfile.read()  # バイト列として読み込んでいる
reader = csv.reader(decoded_file)
for row in reader:

ちなみに、open()関数で'rb'というモードを指定している場合もファイルがバイナリモードで開かれているので、同じくエラーが発生します。csv.readerは文字列を期待しているからですね。

解決方法

エラーメッセージの通り、ファイルがテキストモードで開かれていないのが原因なので、csv.readerに渡す前にテキストモードで開けば解決します。以下のように変更するとエラーがなくなりました。

csvfile = request.FILES['file']
decoded_file = csvfile.read().decode('utf-8-sig').splitlines()
reader = csv.reader(decoded_file)
for row in reader:

上記では、.decode('utf-8-sig')を使用してバイト列をUTF-8エンコーディングでデコードし、テキストに変換します。

decode('utf-8-sig')については、BOM除去という点で一つ詰まった点があります。
BOM除去については以下の記事で記載していますので参考ください。

【Python】CSVを読み込むと文字列の中に\ufeffが入ってしまう場合の原因と解決方法

補足:request.FILES['file']とは

Djangoでは、HTTPリクエストに添付されたファイルを処理するために、request.FILESという属性を提供しています。

request.FILESは、ユーザーがフォームからファイルをアップロードした場合や、APIリクエストの一部としてファイルを送信した場合など、リクエストに含まれるファイルデータを取り扱うための特別なデータ構造です。

'file'部分は、アップロードされたファイルのフィールド名を指定します。
例えば、hogehoge.csvをアップロードした場合、request.FILES['file']をデバッグすればhogehoge.csvと出力されます。また、データの型は<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>というInMemoryUploadedFileクラスになります。ファイルのデータをメモリ内に一時的に保存し、後続の処理で利用することができます。

詳細はDjangoドキュメントからどうぞ。
ファイルのアップロード — Django 4.0.6 ドキュメント

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0