PythonでCSVファイルを出力する方法を初心者向けに解説
はじめに
皆さんは、プログラミング言語の中でも比較的読み書きがしやすいと言われるPythonを使って、ファイルにさまざまな情報を保存してみたいと考えたことはないでしょうか。
このとき候補となるファイル形式はいろいろありますが、特にCSV形式は扱いやすいテキストデータとしても有名です。
例えば、Excelやスプレッドシートなどに簡単にインポートできるのも便利なポイントです。
この記事では、PythonでCSVファイルを出力するときの基本的な使い方から、実務でもよくあるシーンを想定した具体的な例までを紹介していきます。
プログラミング初心者の方にもわかりやすい表現を心がけつつ、なるべくイメージが湧きやすい例を取り入れます。
初めてPythonでCSVファイルを書き出す方でも、作業の流れが理解できるように進めてみましょう。
この記事を読むとわかること
- CSV形式とは何か、どのようなシーンで使われるのか
- PythonでCSVファイルを書き込む方法の全体像
- Python標準モジュールであるcsvモジュールの基本的な使い方
- 実務のシーンを想定した活用の仕方や注意点
- エラーを防ぐためのポイントや例外的なケースへの対応イメージ
ここから先は、具体的なコード例や実践的な解説も交えながら、初心者の皆さんが「ああ、こうやって書けばよいんだな」と思える内容を目指しています。
少し長い記事ですが、気になるところだけつまみ読みしてみても、きっと理解が深まるはずです。
PythonでCSV出力を行うための基本知識
CSVとは何か
CSVは、Comma Separated Values(カンマ区切り値)の略称です。
テキストファイルの中で各項目をカンマで区切り、一つの行が一つのレコードに相当します。
多くのソフトウェアやプログラミング言語で取り扱いやすいため、データをやり取りするときに頻繁に使われています。
ExcelやGoogleスプレッドシートに取り込むと、カンマごとにセルが分割されるため、テーブル形式のデータとして簡単に扱えるのも便利な点です。
一方で、項目の中にカンマが含まれるケースや改行が含まれるケースでは、文字列をダブルクォーテーションで囲む必要があるなど、ある程度の規則を守る必要があります。
ですが、慣れてしまえば特に難しいものではありません。
CSVファイルを実務で使うケース
実務においては、例えば下記のようなケースでPythonとCSVファイルの出力機能が役立つことが多いです。
- 顧客リストや会員データをDB(データベース)から取り出して、CSVとして社内システムや外部ツールに渡す
- 売上データや在庫データをCSVファイルとして出力し、各チームへ共有する
- あるいは、分析用のデータを機械学習ツールに渡す際などに簡単に読み込み可能な形式に整える
このように、開発現場でも日々使われる基本的なファイル形式なので、PythonプログラムからCSV出力ができるようになると、一気に作業の幅が広がります。
カンマ区切りのルールやエンコードの扱いに気をつけるだけで、多くのシステムとデータを受け渡しできるのがメリットです。
一方で、コロンやタブなど、カンマ以外の文字を区切りに使うTSV(Tab Separated Values)のような類似フォーマットもあります。
状況によっては区切り文字を柔軟に変えるケースもあるため、それも念頭に置くとよりスムーズに運用できるでしょう。
PythonでCSVファイルを書き込む基本方法
Python標準ライブラリcsvモジュールの概要
PythonでCSVファイルを扱うときは、csvという標準モジュールを使うのが一般的です。
専用の関数が用意されており、簡単なコードでCSV書き込みや読み込みができます。
特別な外部パッケージをインストールしなくても、Pythonをインストールすればすぐに使えるのも便利な点です。
このモジュールを使う一番のポイントは、Excelや他ツールとデータをやり取りするときに利用されるような一般的なCSV形式を簡単に再現できることです。
文字列にカンマや改行が含まれた場合でも自動的にダブルクォーテーションをつけてくれるため、手作業でカンマをエスケープする必要がありません。
CSVファイルへの書き込み手順
基本的な書き込みの流れは以下のとおりです。
- ファイルを開く: Pythonの組み込み関数
open()
で書き込み先のファイルを開く - csv.writer()を利用してライターオブジェクトを作成する
- writerow()やwriterows()メソッドを使って行を書き込む
- ファイルを閉じる:
with
構文を使えば自動的に閉じる処理を行ってくれる
サンプルコードを見ながら理解するとわかりやすいでしょう。
import csv # 書き込み用のサンプルデータ data = [ ["id", "name", "age"], [1, "Taro", 25], [2, "Hanako", 30], [3, "Ken", 28] ] # CSVファイルへ書き込む例 with open("sample_output.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.writer(f) for row in data: writer.writerow(row)
1行ずつリストの形で書き込みを行っています。
カンマ区切りで書かれるので、ファイルを開いてみると各要素がカンマで区切られた状態になります。
newline=""
としているのは、Windows環境などで余分な改行を挿入されるのを防ぐための方法です。
Pythonの公式ドキュメントでも推奨されている書き方なので、CSVを書く際には覚えておくと便利です。
実務で押さえておきたいポイント
実務でCSVファイルを出力するときには、以下のような点に注意するとミスを防げます。
- encoding引数を忘れない: 文字化けを防ぐために、
utf-8
など目的のエンコードを明示する - header (ヘッダー行) の扱い: 1行目にヘッダーを記載するかどうかを事前に決める
- 区切り文字や囲み文字を変更する必要はないか: デフォルトはカンマ区切りでダブルクォーテーションですが、要件によってはセミコロンやタブが必要になることもある
- 改行コードの違い: OSによって改行コードが変わる可能性もあるので、
newline=""
の指定をしておくとよい
こうしたポイントを抑えておけば、後から他のツールでデータを開いたときにフォーマットが崩れるといったトラブルを減らせます。
csv.writerとcsv.DictWriterの違い
csv.writerの特徴
先ほどの例にもあったように、csv.writer
は基本的にリストやタプルのリストを渡して書き込みを行います。
これは、カラム名や実際のデータをインデックス順で扱うことになります。
たとえば、row[0]
がID、row[1]
が名前、といったように、順番で意味付けを行うわけです。
この方法でも充分にCSVは書けますが、実務で扱うデータは辞書形式の場合が多いかもしれません。
そんなときに便利なのが、csv.DictWriter
です。
csv.DictWriterの特徴
csv.DictWriter
を使うと、Pythonの辞書オブジェクトを使ってCSVの行を書き込めます。
たとえば、フィールド名が"ID"、"NAME"、"AGE"のようにキーとして存在し、値も辞書で格納されている場合に便利です。
import csv # 辞書形式のデータ例 data_dicts = [ {"id": 1, "name": "Taro", "age": 25}, {"id": 2, "name": "Hanako", "age": 30}, {"id": 3, "name": "Ken", "age": 28} ] fieldnames = ["id", "name", "age"] with open("sample_dict_output.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() # ヘッダーを書き込む for row in data_dicts: writer.writerow(row)
この例では、fieldnames
というリストで列の順番を定義しています。
writeheader()
メソッドを使うと、指定したフィールド名が1行目に書き込まれます。
この書き方だと、単純に辞書を渡すだけなので、コードを読む人にとっては「idとnameとageの列なんだな」とすぐに理解できるのも利点です。
データが複数の辞書になっている場合や、データベースからレコードを取得した際にそのまま辞書として受け取るような場合は特に便利です。
区切り文字やクォート文字を変えたい場合
delimiterやquotecharの指定
標準のcsv.writer
やcsv.DictWriter
は、カンマを区切り文字(delimiter)とし、文字列をダブルクォーテーションで囲むのが基本です。
しかし、実務では区切り文字がタブで求められる場合や、クォートがシングルクォーテーションの場合もあるでしょう。
その場合は、csv.writer
やcsv.DictWriter
を作るときにパラメータを渡すことで設定を変えられます。
import csv data = [ ["id", "name", "age"], [1, "Taro", 25], [2, "Hanako", 30] ] with open("sample_tab_separated.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.writer(f, delimiter="\t", quotechar="'") for row in data: writer.writerow(row)
このコードでは区切り文字をタブに、囲み文字をシングルクォーテーションに変えています。
タブ区切りの場合、拡張子を.tsv
にすることもありますが、システムによっては拡張子が.csv
のままでも問題なく扱える場合があります。
quotingの設定
csvモジュールには、さらにどのタイミングでクォートを行うかを制御するためのquoting
というパラメータもあります。
例えば、csv.QUOTE_ALL
を指定すれば、常にダブルクォーテーションで項目を囲むようになります。
import csv data = [ ["id", "name", "age"], [1, "Taro, Yokohama", 25], [2, "Hanako", 30] ] with open("sample_quote_all.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.writer(f, delimiter=",", quotechar='"', quoting=csv.QUOTE_ALL) for row in data: writer.writerow(row)
カンマを含む文字列を明示的にダブルクォーテーションで囲んで出力したいときは、こうした設定が役立ちます。
実務の要件に応じて、クォートのポリシーを変えることでツールの取り込みがスムーズになるでしょう。
既存ファイルへの追記と上書き
追記モード(mode="a")を使う
CSVファイルを日次で追記していきたいケースでは、ファイルを開くときに「追記モード」にする方法があります。
Pythonのopen()
関数でファイルを開くときに、mode="a"
を指定すると追記できます。
import csv new_data = [ ["4", "Mike", 22], ["5", "Saki", 27] ] with open("sample_output.csv", mode="a", encoding="utf-8", newline="") as f: writer = csv.writer(f) for row in new_data: writer.writerow(row)
上記のように書くと、すでに存在するsample_output.csv
の末尾に新しい行が追加されます。
ただし、この場合はすでにヘッダーが書き込まれている可能性があるため、writer.writeheader()
のようにヘッダーを再度書き込むと重複してしまうかもしれません。
よって、実務で追記する際には**「ヘッダーの書き込みは初回だけ」**などのルールを決めておきましょう。
上書きモード(mode="w")の注意点
初期化するつもりで上書きモードを使うときは、ファイルの中身が完全に上書きされる点に注意が必要です。
誤って重要なデータを消してしまわないように、処理の順番を考慮するか、ファイルを分けて作業する方法が安全です。
業務上、間違ってデータを消してしまうと大きな問題につながるかもしれないので、特に注意してください。
文字エンコーディングと改行コード
文字エンコーディングの重要性
日本語を扱う場合には、open()
でファイルを開くときにencoding="utf-8"
を明示的に指定することが多いでしょう。
このエンコーディング指定をし忘れると、Windows環境であればShift-JIS(cp932)がデフォルトになる場合があり、他の環境と互換性をとる際に文字化けするリスクが高まります。
よって、基本的にはencoding="utf-8"
を指定しておけば、広い環境で開けるCSVファイルになる傾向があります。
もし、組織やプロジェクトのルールでShift-JISが必要だと決まっているなら、encoding="cp932"
のように指定して出力すれば問題ありません。
ただし、その場合でも後で文字化けしやすいため、事前に要件をしっかり確認しておくことが大切です。
改行コードの扱い
Pythonでファイル書き込みをするときは、基本的にOS依存の改行コードが使われます。
例えばWindowsの場合はCR+LF(\r\n)
、LinuxやmacOSではLF(\n)
となるのが一般的です。
しかし、CSVファイルを扱うときは、意図しない改行が入ってしまうとデータを読み込むアプリケーション側で問題が起きることがあります。
そこで、newline=""
という引数を指定して、余計な改行が入らないようにする書き方が推奨されています。
Pythonのcsvモジュールのドキュメントでも、例示としてnewline=""
を使うようになっています。
改行コードに関しては、読み込む側の仕様とも関係しますが、newline=""
をセットしておくほうが安心です。
単純に覚えておけば、事故を減らせるでしょう。
実務シーン:売上データの書き出し例
ここでは、もう少しビジネス向けの例を想定し、売上データをCSVファイルに出力する場合を考えてみます。
皆さんがもし、ECサイトの受注テーブルからデータをPythonで取得して、CSVファイルを外部担当に渡すことになったら、下記のようなコードを書きたくなるでしょう。
受注データをリストで受け取ったケース
まずは、受注データをリストのリストで受け取っていると想定します。
import csv # ダミーの売上データ(リストのリスト形式) # [受注ID, 商品名, 個数, 金額, 購入日時] orders = [ [101, "USBメモリ 32GB", 2, 2000, "2025-02-15 10:30:00"], [102, "ワイヤレスマウス", 1, 1500, "2025-02-15 11:00:00"], [103, "ノートPCスタンド", 1, 3000, "2025-02-15 12:20:00"], ] with open("orders.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.writer(f) # ヘッダー行を書き込む writer.writerow(["受注ID", "商品名", "個数", "金額", "購入日時"]) # データを書き込む for order in orders: writer.writerow(order)
この例ではヘッダーを手動で指定していますが、実務シーンなら区切り文字やエンコードなども注意しながら、システムで使いやすい形に仕上げていきます。
外部の担当者がExcelで開くかもしれませんし、別の業務システムにインポートするかもしれません。
その目的に合わせて、ファイル名や列順、ヘッダーの名称を調整するとスムーズなやり取りができるでしょう。
受注データを辞書形式で受け取ったケース
受注データが辞書形式の場合は、csv.DictWriter
を活用するとコードがさらにわかりやすくなります。
import csv # ダミーの売上データ(辞書形式) orders_dict = [ {"order_id": 101, "product_name": "USBメモリ 32GB", "quantity": 2, "price": 2000, "order_date": "2025-02-15 10:30:00"}, {"order_id": 102, "product_name": "ワイヤレスマウス", "quantity": 1, "price": 1500, "order_date": "2025-02-15 11:00:00"}, {"order_id": 103, "product_name": "ノートPCスタンド", "quantity": 1, "price": 3000, "order_date": "2025-02-15 12:20:00"}, ] fieldnames = ["order_id", "product_name", "quantity", "price", "order_date"] with open("orders_dict.csv", mode="w", encoding="utf-8", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for row in orders_dict: writer.writerow(row)
このように、受注IDや商品名などが一目でわかる形でコードを読み書きできるのはメリットです。
ただ、業務によってはデータを取得する段階でリスト形式か辞書形式かが決まっているので、それに合わせて使い分けるとよいでしょう。
実務シーン:外部APIから取得した情報をCSVにまとめる
別の例として、外部APIからJSON形式でデータを取得し、それをCSVとして保存するケースを考えてみましょう。
ここでは架空のAPIから「ユーザーのID・名前・メールアドレス」を取得できると仮定します。
import csv import requests # ダミーのAPI URL(実際には存在しないものとする) API_URL = "https://api.example.com/users" response = requests.get(API_URL) # たとえば下記のようなJSONデータが返ってくると想定 # [ # {"id": 1, "name": "Taro", "email": "taro@example.com"}, # {"id": 2, "name": "Hanako", "email": "hanako@example.com"}, # ] users_data = response.json() # CSVに書き出す with open("users_data.csv", mode="w", encoding="utf-8", newline="") as f: fieldnames = ["id", "name", "email"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for user in users_data: writer.writerow(user)
このように、APIからJSON形式で取得したデータを辞書リストの形で扱い、そのままCSVファイルに落とし込むのはよくあるパターンです。
実際には例外処理やエラー時のリトライ処理などが必要になる場合もあります。
また、API応答が大量のデータを返す場合にはメモリ使用量に気を配ることもあります。
しかし、CSVに書き込む基本的なフローは変わりません。
要するに、以下の順序で行えばよいのです。
- APIからデータを取得する
- JSONや辞書形式に変換(Pythonの
requests
ライブラリを使うと便利) - CSV出力のためにフィールド名とデータを用意する
DictWriter
で書き込む
大量データを書き込むときの工夫
メモリ消費量のコントロール
大量のデータを書き込む場合には、一度に全部をリストに格納するとメモリに負担がかかります。
そのようなケースでは、取得したデータを1件ずつあるいは チャンク (塊) 単位でCSVに書き込む方法を取るといいでしょう。
たとえばデータベースから10,000件、100,000件とレコードがある場合、全件をリストに格納してからcsv.writerに渡すのではなく、ストリーミング的に書き込むイメージです。
Pythonでは、ジェネレーターを使ってデータを少しずつ処理する仕組みを作ったり、APIの応答をページネーションしながら取得することが多いです。
例として、以下のようなコードイメージです。
import csv def fetch_records_in_chunks(chunk_size): # ダミーのジェネレーター関数 # 実際にはDBやAPIからchunk_size件ずつデータを取る処理を書く # ここではイメージとして2回に分けて返す yield [ {"id": 1, "name": "A", "email": "a@example.com"}, {"id": 2, "name": "B", "email": "b@example.com"} ] yield [ {"id": 3, "name": "C", "email": "c@example.com"}, {"id": 4, "name": "D", "email": "d@example.com"} ] with open("large_data.csv", mode="w", encoding="utf-8", newline="") as f: fieldnames = ["id", "name", "email"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() # チャンク単位で取得して書き込む for records in fetch_records_in_chunks(2): for record in records: writer.writerow(record)
このようにしておけば、大量のデータでも一度に全部をメモリに読み込むことを防げます。
実務では大規模なデータを扱うことも珍しくないので、覚えておくと便利なテクニックでしょう。
パフォーマンス向上のヒント
さらに、大量データを扱うときのパフォーマンスを上げたい場合には、ファイル書き込みの回数を減らすなどの対策も考えられます。
例えば、一気にまとめてwriter.writerows()
を使って書き込む方法です。
import csv rows_to_write = [ [1, "Taro", 25], [2, "Hanako", 30], [3, "Ken", 28] ] with open("bulk_output.csv", "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerows(rows_to_write)
1行ずつwriter.writerow()
を呼ぶよりもwriter.writerows()
でまとめて書いたほうが内部的に高速になるケースがあります。
ただし、1回で処理できるサイズには限度があるかもしれませんし、メモリの状況にもよります。
データの量や仕組みに合わせて最適な方法を探るのが現場では重要です。
エラーや例外的なケースへの対応
ファイルパスやディレクトリが存在しない
ファイルを書き込む際、指定したディレクトリが存在しない場合や、書き込み権限がないディレクトリを指定してしまうことがあります。
その場合、open()
でエラーが発生するので、例外処理を行うか、事前にディレクトリが存在するかをチェックしておくのがベターです。
import os import csv output_dir = "output_data" os.makedirs(output_dir, exist_ok=True) # ディレクトリがなければ作成 file_path = os.path.join(output_dir, "sample_output.csv") with open(file_path, mode="w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerow(["ID", "Name"]) writer.writerow([1, "Taro"])
こうしておけば、ディレクトリがない場合でも強制的に作成され、CSVを書き込めます。
データに不正な値が混じっている
例えば、文字列だと思っていた部分に制御文字が含まれている、想定していない型が来てしまった、などのパターンです。
これも実務では起こりやすいことです。
単純には、書き込み前にバリデーションチェックを行ってエラー値を弾く、もしくはエラー行をログに記録するといった方法があります。
Pythonのcsv.writerは基本的に「文字列として出力する」という動きなので、型が異なっていても書き込めてしまうこともあります。
しかし、後で読み込むときに期待した型と合わずにトラブルになることがあるので、実務ではデータの前処理(クリーニング)も大切です。
pandasを使ったCSV出力(補足)
Pythonのデータ分析ライブラリであるpandasを使うと、CSVファイルの読み書きがさらに直感的に行えます。
ただし、pandasは標準ライブラリではないため、必要に応じてインストールする必要があります。
ここでは補足として紹介しますが、実務で表形式のデータをかなり扱う場合には、pandasのDataFrame
を利用することが多いです。
import pandas as pd data = { "id": [1, 2, 3], "name": ["Taro", "Hanako", "Ken"], "age": [25, 30, 28] } df = pd.DataFrame(data) df.to_csv("pandas_output.csv", index=False, encoding="utf-8")
pandasを使えば列名やインデックスを簡単に指定でき、さらに型の変換なども簡単です。
ただし、ここでは標準モジュールのcsv
を中心に解説しているため、詳細は割愛します。
便利なライブラリや関連テクニック
Python以外の形式に変換
CSVだけでなく、JSON形式での保存やXML形式、あるいはExcelファイル(XLSX)などに直接書き込むライブラリも存在します。
しかし、まずは**「汎用性の高いCSV」**でどこにでもデータをやり取りできるようにしておくと、特に初心者の方には扱いやすいはずです。
CSV読み込みの方も理解しておく
出力だけでなく、CSVの読み込み(csv.reader
やcsv.DictReader
)の方も理解しておくと、ひととおりの入出力処理をこなせます。
実務上は、外部から送られてきたCSVを取り込んで処理し、その結果をまたCSVで返すようなフローが多いので、ぜひ合わせて学んでおくといいでしょう。
バージョン互換性
Pythonのバージョンによっては細かな挙動の違いが生じる場合もありますが、csvモジュール自体はPython 3系で安定しています。
現在利用する環境のPython 3系であれば、基本的な使い方は大きく変わらないはずです。
大事なのは、プログラムが期待通りに動作するかどうかを確認し、テストもしておくことです。
業務に導入するときは、一度実際に書き込み、生成したCSVをExcelやスプレッドシートなどで開いてみるテストをすると安心できます。
よくある質問や注意点
ダブルクォーテーションの表示を抑制したい
実際にExcelなどで開くと、ダブルクォーテーションが目立ってしまうケースがあります。
しかし、Excelやスプレッドシートで表示するときには、ダブルクォーテーションはエスケープ用のものなので、通常は表示されないことが多いです。
もしテキストエディタで開いたときにダブルクォーテーションだらけに見えても、CSVの仕様上は問題ありません。
どうしても見た目をシンプルにしたいなら、quoting=csv.QUOTE_MINIMAL
(デフォルト設定)やquoting=csv.QUOTE_NONE
を試してみましょう。
ただし、カンマや改行を含む文字列が出現する場合には、囲まないといけないので、実務でQUOTE_NONE
は推奨しにくいという点に注意してください。
BOM付きUTF-8で出力してほしいといわれたら?
一部の環境では、Excelで開く際にBOM付きのUTF-8(UTF-8 with BOM)でないと文字化けするというケースもあります。
その場合には、ファイル書き込み時にエンコードを"utf-8-sig"
に指定するとBOM付きになるので対応可能です。
with open("bom_output.csv", mode="w", encoding="utf-8-sig", newline="") as f: writer = csv.writer(f) writer.writerow(["ID", "Name"]) writer.writerow([1, "Taro"])
特定のツールや環境によって要望が異なるので、実務では仕様をよく確認してください。
まとめ
ここまで、Pythonを使ってCSVファイルを出力する方法について、一連の流れを解説してきました。
- CSVとは何かという基本的な概念
- csvモジュールを使った具体的な書き込み手順(
csv.writer
とcsv.DictWriter
) - 実務のシーンを意識したデータの扱い方や設定方法
- 大量データやエンコーディングなど実際によく直面する課題への対応のしかた
こうしたポイントを覚えておけば、実際の開発や業務でもスムーズにCSVファイルを出力できるようになるでしょう。
皆さんが扱うプロジェクトの要件や環境に合わせて、ぜひ活用してみてください。
役立つテクニックは多岐にわたりますが、まずはシンプルなcsv.writerで小さなデータを書き出してみるところからスタートしてみると理解しやすいと思います。
複雑な要件がある場合は、DictWriter
を駆使するなり、区切り文字やクォート文字を調整するなりして、要件に合ったCSVを柔軟に生成してください。
不明点があれば、まずはコードを少しずつ試しながら、作成したCSVをExcelやスプレッドシートで開いて動作を確認してみるのがおすすめです。
ぜひ、PythonでのCSV出力をマスターして、日常の作業や開発をさらに便利に進めてみてください。