【Python】csvを出力すると文字化けする原因と対処法を解説

この記事では、CSVファイルの文字化けの原因とその対処法について、初心者にもわかりやすく解説します。

具体的なコード例も紹介するので、実際に試してみてください。

目次から探す

CSVファイルの文字化けとは

CSVファイルは、データをカンマ区切りで保存するシンプルなテキスト形式のファイルです。

Pythonを使ってデータをCSVファイルに出力することはよくありますが、出力したCSVファイルを開いたときに文字化けが発生することがあります。

文字化けが発生するシチュエーション

文字化けが発生するシチュエーションは主に以下のような場合です。

エンコーディングの不一致

CSVファイルを出力する際に使用したエンコーディングと、ファイルを読み込む際に使用するエンコーディングが一致しない場合、文字化けが発生します。

例えば、PythonでUTF-8エンコーディングを使用してCSVファイルを出力し、そのファイルをShift_JISエンコーディングで読み込むと、文字化けが発生します。

CSVライブラリのデフォルト設定

Pythonのcsvモジュールやpandasのto_csvメソッドを使用してCSVファイルを出力する際、デフォルトのエンコーディングがUTF-8に設定されていることが多いです。

しかし、Excelなどの一部のアプリケーションはデフォルトでShift_JISを使用するため、エンコーディングの不一致が原因で文字化けが発生することがあります。

ファイルの保存形式の違い

CSVファイルを保存する際に、BOM(Byte Order Mark)を付加するかどうかも文字化けに影響します。

BOMは、ファイルの先頭に付加される特殊なバイト列で、エンコーディングを示す役割を持ちます。

BOMが付加されていないUTF-8ファイルを、BOM付きのUTF-8ファイルとして読み込むと、文字化けが発生することがあります。

以上のように、文字化けはエンコーディングの不一致やファイルの保存形式の違いなど、さまざまな要因で発生します。

次のセクションでは、具体的な文字化けの原因について詳しく解説します。

文字化けの原因

CSVファイルの文字化けは、主にエンコーディングの不一致やCSVライブラリのデフォルト設定が原因で発生します。

ここでは、それぞれの原因について詳しく解説します。

エンコーディングの不一致

エンコーディングとは、文字をバイト列に変換する方法のことです。

異なるエンコーディングを使用すると、文字化けが発生することがあります。

UTF-8とShift_JISの違い

UTF-8とShift_JISは、代表的なエンコーディング方式です。

UTF-8は、国際的に広く使われているエンコーディングで、多くの文字を効率的に表現できます。

一方、Shift_JISは日本語に特化したエンコーディング方式で、特にWindows環境でよく使われます。

例えば、UTF-8でエンコードされたファイルをShift_JISでデコードしようとすると、文字化けが発生します。

これは、各エンコーディング方式が異なるバイト列を使用しているためです。

エンコーディングの自動判別の限界

多くのテキストエディタやプログラムは、ファイルのエンコーディングを自動で判別しようとしますが、完全に正確ではありません。

特に、CSVファイルのようにデータが混在している場合、誤ったエンコーディングが選択されることがあります。

CSVライブラリのデフォルト設定

Pythonには、CSVファイルを扱うためのライブラリがいくつかありますが、それぞれのデフォルト設定が異なるため、文字化けが発生することがあります。

Pythonのcsvモジュール

Pythonの標準ライブラリであるcsvモジュールは、デフォルトでエンコーディングを指定しません。

そのため、システムのデフォルトエンコーディングが使用されます。

WindowsではShift_JISがデフォルトエンコーディングとして設定されていることが多く、これが原因で文字化けが発生することがあります。

import csv
# 文字化けする可能性のあるコード例
with open('example.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['名前', '年齢'])
    writer.writerow(['山田太郎', 30])

pandasのto_csvメソッド

pandasライブラリのto_csvメソッドも、デフォルトではエンコーディングを指定しません。

これにより、特に日本語を含むデータを扱う場合に文字化けが発生することがあります。

import pandas as pd
# 文字化けする可能性のあるコード例
df = pd.DataFrame({'名前': ['山田太郎', '鈴木次郎'], '年齢': [30, 25]})
df.to_csv('example.csv', index=False)

これらの原因を理解することで、適切な対処法を講じることができます。

次のセクションでは、具体的な対処法について解説します。

文字化けの対処法

CSVファイルの文字化けを防ぐためには、主にエンコーディングを正しく指定することが重要です。

また、場合によっては文字コードの変換ツールを使用することも有効です。

以下では、具体的な対処法について詳しく解説します。

エンコーディングを指定する

csvモジュールでのエンコーディング指定

Pythonの標準ライブラリであるcsvモジュールを使用する場合、エンコーディングを指定することで文字化けを防ぐことができます。

以下に具体的なコード例を示します。

import csv
# データを用意
data = [
    ["名前", "年齢", "住所"],
    ["山田太郎", 30, "東京都"],
    ["鈴木花子", 25, "大阪府"]
]
# CSVファイルに書き込む
with open('output.csv', 'w', newline='', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(data)

この例では、open関数encoding引数に'utf-8'を指定しています。

これにより、UTF-8エンコーディングでCSVファイルが作成され、文字化けを防ぐことができます。

pandasでのエンコーディング指定

pandasライブラリを使用する場合も、エンコーディングを指定することで文字化けを防ぐことができます。

以下に具体的なコード例を示します。

import pandas as pd
# データを用意
data = {
    "名前": ["山田太郎", "鈴木花子"],
    "年齢": [30, 25],
    "住所": ["東京都", "大阪府"]
}
# DataFrameを作成
df = pd.DataFrame(data)
# CSVファイルに書き込む
df.to_csv('output_pandas.csv', index=False, encoding='utf-8')

この例では、to_csvメソッドencoding引数に'utf-8'を指定しています。

これにより、UTF-8エンコーディングでCSVファイルが作成され、文字化けを防ぐことができます。

文字コードの変換ツールを使用する

エンコーディングを指定しても文字化けが発生する場合や、既に文字化けしているファイルを修正する場合には、文字コードの変換ツールを使用することが有効です。

iconvコマンドの使用方法

iconvは、文字コードを変換するためのコマンドラインツールです。

以下に使用例を示します。

iconv -f SHIFT_JIS -t UTF-8 input.csv -o output.csv

このコマンドは、input.csvファイルをShift_JISからUTF-8に変換し、output.csvとして出力します。

-fオプションで入力ファイルのエンコーディングを、-tオプションで出力ファイルのエンコーディングを指定します。

Pythonでの文字コード変換

Pythonを使用して文字コードを変換することも可能です。

以下に具体的なコード例を示します。

# 文字コード変換関数
def convert_encoding(input_file, output_file, from_enc, to_enc):
    with open(input_file, 'r', encoding=from_enc) as infile:
        content = infile.read()
    with open(output_file, 'w', encoding=to_enc) as outfile:
        outfile.write(content)
# 変換を実行
convert_encoding('input.csv', 'output.csv', 'shift_jis', 'utf-8')

この例では、convert_encoding関数を定義し、入力ファイルのエンコーディングをfrom_enc、出力ファイルのエンコーディングをto_encとして指定しています。

input.csvファイルをShift_JISからUTF-8に変換し、output.csvとして出力します。

以上の方法を用いることで、CSVファイルの文字化けを防ぐことができます。

エンコーディングを正しく指定することが最も基本的な対処法ですが、場合によっては文字コードの変換ツールを使用することも有効です。

実際のコード例

ここでは、実際にPythonのコードを使ってCSVファイルを出力する際の文字化けの例と、その対処法を紹介します。

具体的には、Pythonの標準ライブラリであるcsvモジュールと、データ解析ライブラリであるpandasを使った例を見ていきます。

csvモジュールを使った例

文字化けするコード例

まずは、csvモジュールを使ってCSVファイルを出力する際に文字化けが発生する例を見てみましょう。

import csv
# データを用意
data = [
    ["名前", "年齢", "住所"],
    ["山田太郎", 30, "東京都"],
    ["鈴木花子", 25, "大阪府"]
]
# CSVファイルに書き込む
with open('output.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)

このコードを実行すると、output.csvファイルが生成されます。

しかし、エンコーディングを指定していないため、デフォルトのエンコーディング(通常はUTF-8)が使用されます。

このファイルをExcelなどで開くと、文字化けが発生することがあります。

文字化けを防ぐコード例

文字化けを防ぐためには、エンコーディングを明示的に指定する必要があります。

以下のコードでは、utf-8-sigエンコーディングを指定しています。

import csv
# データを用意
data = [
    ["名前", "年齢", "住所"],
    ["山田太郎", 30, "東京都"],
    ["鈴木花子", 25, "大阪府"]
]
# CSVファイルに書き込む
with open('output.csv', 'w', newline='', encoding='utf-8-sig') as file:
    writer = csv.writer(file)
    writer.writerows(data)

このコードを実行すると、output.csvファイルが生成され、Excelなどで開いても文字化けが発生しません。

pandasを使った例

文字化けするコード例

次に、pandasを使ってCSVファイルを出力する際に文字化けが発生する例を見てみましょう。

import pandas as pd
# データを用意
data = {
    "名前": ["山田太郎", "鈴木花子"],
    "年齢": [30, 25],
    "住所": ["東京都", "大阪府"]
}
df = pd.DataFrame(data)
# CSVファイルに書き込む
df.to_csv('output_pandas.csv', index=False)

このコードを実行すると、output_pandas.csvファイルが生成されます。

しかし、エンコーディングを指定していないため、デフォルトのエンコーディング(通常はUTF-8)が使用されます。

このファイルをExcelなどで開くと、文字化けが発生することがあります。

文字化けを防ぐコード例

文字化けを防ぐためには、エンコーディングを明示的に指定する必要があります。

以下のコードでは、utf-8-sigエンコーディングを指定しています。

import pandas as pd
# データを用意
data = {
    "名前": ["山田太郎", "鈴木花子"],
    "年齢": [30, 25],
    "住所": ["東京都", "大阪府"]
}
df = pd.DataFrame(data)
# CSVファイルに書き込む
df.to_csv('output_pandas.csv', index=False, encoding='utf-8-sig')

このコードを実行すると、output_pandas.csvファイルが生成され、Excelなどで開いても文字化けが発生しません。

以上のように、PythonでCSVファイルを出力する際には、エンコーディングを明示的に指定することで文字化けを防ぐことができます。

特に、utf-8-sigエンコーディングを使用することで、Excelなどのアプリケーションでも正しく表示されるようになります。

目次から探す