{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ファイルの入出力" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルへの書き込み" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここでは、以下のオブジェクトの内容をテキストファイルとして書き出す例を示す。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "d = {\n", " '東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "まず、インタプリタ上でこのオブジェクトの内容を表示するコードは以下の通り。" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "for ja, (yomi, en) in d.items():\n", " print(ja, yomi, en)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルを書き込みモードで開くには、[open](https://docs.python.org/ja/3/library/functions.html#open)関数の第1引数にファイル名、第2引数に`'w'`を指定し、戻り値としてファイルオブジェクトを受け取る。そして、print関数を呼び出すときに、`file`という引数にファイルオブジェクトを渡す。ファイルへの書き出しが終わったら、close関数でファイルを閉じる。" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "fo = open('prefecture.txt', 'w')\n", "for ja, (yomi, en) in d.items():\n", " print(ja, yomi, en, file=fo)\n", "fo.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "catコマンド(ファイルの内容を表示するコマンド)で出力内容を確認してみる。" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "!cat prefecture.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、close関数を呼び出すのを忘れると、ファイルに内容が書き込まれないことがある。" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "fo = open('prefecture2.txt', 'w')\n", "for ja, (yomi, en) in d.items():\n", " print(ja, yomi, en, file=fo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "catコマンドを呼び出しても、書き出した内容が表示されない。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "!cat prefecture2.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここでclose関数を呼び出すと、ファイルに内容が書き込まれる。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "fo.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "今度はcatコマンドで書き出した内容が表示された。" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "!cat prefecture2.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルの閉じ忘れを防ぐ構文として[with](https://docs.python.org/ja/3/reference/compound_stmts.html#with)文が便利。普段から以下のように記述しておくとよい。" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "with open('prefecture3.txt', 'w') as fo:\n", " for ja, (yomi, en) in d.items():\n", " print(ja, yomi, en, file=fo)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "!cat prefecture3.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "print関数の代わりに、ファイルオブジェクトの[write](https://docs.python.org/ja/3/library/io.html#io.BufferedIOBase.write)関数を用い、文字列を書き出すこともできる。write関数を用いる場合は、改行が出力されないので、出力する文字列の中に改行を含める。" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "with open('prefecture4.txt', 'w') as fo:\n", " for ja, (yomi, en) in d.items():\n", " fo.write(f'{ja} {yomi} {en}\\n')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "!cat prefecture4.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルからの読み込み" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルを読み込みモードで開くには、[open](https://docs.python.org/ja/3/library/functions.html#open)関数の第1引数にファイル名を指定するだけでよい(第2引数に`'r'`がデフォルトで指定される)。ファイルオブジェクトに対してfor文で反復処理を行うと、ファイルから1行ずつ読み出すことができる。ただし、読み出された各行(`line`)の末尾の改行は取り除かれない。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "\n", "神奈川 かながわ Kanagawa\n", "\n", "千葉 ちば Chiba\n", "\n", "埼玉 さいたま Saitama\n", "\n" ] } ], "source": [ "with open('prefecture.txt') as fi:\n", " for line in fi:\n", " print(line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "末尾の改行を取り除くには、strip関数などを用いる。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京 とうきょう Tokyo\n", "神奈川 かながわ Kanagawa\n", "千葉 ちば Chiba\n", "埼玉 さいたま Saitama\n" ] } ], "source": [ "with open('prefecture.txt') as fi:\n", " for line in fi:\n", " print(line.strip('\\n'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "各行はスペース区切りで値が格納されているので、split関数で値を取り出し、辞書にセットすることで、元のオブジェクト`d`を復元できる。" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "r = {}\n", "with open('prefecture.txt') as fi:\n", " for line in fi:\n", " values = line.strip('\\n').split(' ')\n", " r[values[0]] = values[1:]" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']}" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSV" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "コンマ区切り形式(CSV)ファイルの読み書きには、csvモジュールが便利である。" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "import csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のオブジェクトをCSV形式で書き出す例を示す。。" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "d = {\n", " '東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "CSVファイルに書き出すには、[csv.writer](https://docs.python.org/ja/3/library/csv.html#csv.writer)オブジェクトを作成し、[writerow](https://docs.python.org/ja/3/library/csv.html#csv.writer)メソッドなどを呼び出せばよい。" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "with open('prefecture.csv', 'w') as fo:\n", " writer = csv.writer(fo)\n", " for ja, (yomi, en) in d.items():\n", " writer.writerow((ja, yomi, en))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "東京,とうきょう,Tokyo\n", "神奈川,かながわ,Kanagawa\n", "千葉,ちば,Chiba\n", "埼玉,さいたま,Saitama\n" ] } ], "source": [ "!cat prefecture.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "CSVファイルを読み込むには、[csv.reader](https://docs.python.org/ja/3/library/csv.html#reader-objects)を用いる。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r = {}\n", "with open('prefecture.csv') as fi:\n", " reader = csv.reader(fi)\n", " for row in reader:\n", " r[row[0]] = row[1:]\n", "r" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## JSON\n", "\n", "JavaScript Object Notation (JSON) は、オブジェクトの内容をJavaScriptとして解釈できる形式で表現するものである。オブジェクトをCSV形式で保存する場合、オブジェクトの構造と平坦化されたカンマ区切りのリストの間で読み書きの処理が必要であったが、JSON形式を用いると構造を保持したままオブジェクトのそのまま書き出すことができる。最近では、多くのプログラミング言語でJSONを読み書きできるようになっているため、プログラミング言語に依存せずにデータのやり取りを行うために用いられる。JSON形式の読み書きを行うには、[json](https://docs.python.org/ja/3/library/json.html)モジュールをロードする。" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "import json" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のオブジェクトをJSON形式で書き出す例を示す。。" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "d = {\n", " '東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "オブジェクトをJSON形式でファイルに書き出すには、[json.dump](https://docs.python.org/ja/3/library/json.html#json.dump)関数に書き出したいオブジェクトを渡せばよい。" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "with open('prefecture.json', 'w') as fo:\n", " json.dump(d, fo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "デフォルトでは日本語などのASCIIではない文字列がエスケープされてしまうので、書き出された内容が読みづらくなることがある。" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\"\\u6771\\u4eac\": [\"\\u3068\\u3046\\u304d\\u3087\\u3046\", \"Tokyo\"], \"\\u795e\\u5948\\u5ddd\": [\"\\u304b\\u306a\\u304c\\u308f\", \"Kanagawa\"], \"\\u5343\\u8449\": [\"\\u3061\\u3070\", \"Chiba\"], \"\\u57fc\\u7389\": [\"\\u3055\\u3044\\u305f\\u307e\", \"Saitama\"]}" ] } ], "source": [ "!cat prefecture.json" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "そのようなときは、json.dump関数の引数に`ensure_ascii=False`を渡せばよい。" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "with open('prefecture.json', 'w') as fo:\n", " json.dump(d, fo, ensure_ascii=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "書き出されたJSONの表記は、ほぼPythonのオブジェクトの表記と同じである。" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\"東京\": [\"とうきょう\", \"Tokyo\"], \"神奈川\": [\"かながわ\", \"Kanagawa\"], \"千葉\": [\"ちば\", \"Chiba\"], \"埼玉\": [\"さいたま\", \"Saitama\"]}" ] } ], "source": [ "!cat prefecture.json" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "さらに、`indent`引数にインデントの文字数を設定すると、書き出されたJSON表記が読みやすくなる。" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "with open('prefecture.json', 'w') as fo:\n", " json.dump(d, fo, ensure_ascii=False, indent=2)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"東京\": [\n", " \"とうきょう\",\n", " \"Tokyo\"\n", " ],\n", " \"神奈川\": [\n", " \"かながわ\",\n", " \"Kanagawa\"\n", " ],\n", " \"千葉\": [\n", " \"ちば\",\n", " \"Chiba\"\n", " ],\n", " \"埼玉\": [\n", " \"さいたま\",\n", " \"Saitama\"\n", " ]\n", "}" ] } ], "source": [ "!cat prefecture.json" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "JSONファイルを読み出すには、[json.load](https://docs.python.org/ja/3/library/json.html#json.load)関数を呼び出せばよい(これまでにJSON形式で書き出した全ファイルは、JSONとして解釈すれば同じ内容のオブジェクトとして読み出される)。" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'東京': ['とうきょう', 'Tokyo'],\n", " '神奈川': ['かながわ', 'Kanagawa'],\n", " '千葉': ['ちば', 'Chiba'],\n", " '埼玉': ['さいたま', 'Saitama']}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "with open('prefecture.json') as fi:\n", " r = json.load(fi)\n", "r" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字コードを指定したファイルオブジェクト" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "東京都の[くらしと統計2019 運輸・観光](https://www.toukei.metro.tokyo.lg.jp/kurasi/2019/ku19-18.htm)のウェブサイトから[主な駅の乗車人員数(平成28年度)のCSVファイル](https://www.toukei.metro.tokyo.lg.jp/kurasi/2019/csv/ku19rv1810.csv)をダウンロードする。ダウンロードには[wget](https://www.gnu.org/software/wget/)というコマンドを利用している。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--2024-11-24 14:22:31-- https://www.toukei.metro.tokyo.lg.jp/kurasi/2019/csv/ku19rv1810.csv\n", "Resolving www.toukei.metro.tokyo.lg.jp (www.toukei.metro.tokyo.lg.jp)... 3.164.143.93, 3.164.143.8, 3.164.143.45, ...\n", "Connecting to www.toukei.metro.tokyo.lg.jp (www.toukei.metro.tokyo.lg.jp)|3.164.143.93|:443... connected.\n", "HTTP request sent, awaiting response... 404 Not Found\n", "2024-11-24 14:22:31 ERROR 404: Not Found.\n", "\n" ] } ], "source": [ "!wget -O station.csv https://www.toukei.metro.tokyo.lg.jp/kurasi/2019/csv/ku19rv1810.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "catコマンドを使ってダウンロードしたファイルの内容を確認する(文字化けすることはよくある)。" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "!cat station.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルの文字コードはおそらくShift_JIS (cp932) だろうと推測し、iconvで文字コードを変換してみる。" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "!cat station.csv | iconv -f cp932" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "open関数では、ファイルの読み書き時に使用する文字コードを`encoding`パラメータで指定できる。" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "with open('station.csv', encoding='cp932') as fi:\n", " for line in fi:\n", " print(line.strip('\\n'))" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "remove-cell" ] }, "source": [ "---\n", "\n", "[Python早見帳](https://chokkan.github.io/python/) © Copyright 2020-2024 by [岡崎 直観 (Naoaki Okazaki)](https://www.chokkan.org/). この作品はクリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 4.0 国際 ライセンスの下に提供されています。\"クリエイティブ・コモンズ・ライセンス\"" ] } ], "metadata": { "@context": { "CreativeWork": "http://schema.org/CreativeWork", "Organization": "http://schema.org/Organization", "Person": "http://schema.org/Person", "author": "http://schema.org/author", "copyrightHolder": "http://schema.org/copyrightHolder", "copyrightYear": "http://schema.org/copyrightYear", "license": "http://schema.org/license", "name": "http://schema.org/name", "title": "http://schema.org/name", "url": "http://schema.org/url" }, "@type": "CreativeWork", "author": [ { "@type": "Person", "name": "Naoaki Okazaki", "url": "https://www.chokkan.org/" } ], "copyrightHolder": [ { "@type": "Person", "name": "Naoaki Okazaki", "url": "https://www.chokkan.org/" } ], "copyrightYear": 2024, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" }, "license": "https://creativecommons.org/licenses/by-nc-nd/4.0/deed.ja", "title": "Python早見帳" }, "nbformat": 4, "nbformat_minor": 4 }