Skip to content

Instantly share code, notes, and snippets.

@takatakamanbou
Last active October 26, 2020 01:03
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save takatakamanbou/9d22836345c792e24dfc6fc4f3ff023c to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# AProg2020 ex06 Notebook その2\n",
"\n",
"AProgのページ https://www-tlab.math.ryukoku.ac.jp/wiki/?AProg/2020"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"----\n",
"## Pythonのファイル処理(pp.217-228)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Python でファイルを扱う方法をちょっとだけ学びます."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 準備,ファイル読み書きの手順"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"準備として,エディタに以下の内容をコピペして(**JupyterLabでは,Shiftキー押しながら右クリックするとよいでしょう**),いつもの場所に`ex06constants.txt` というファイル名のテキストファイルとして保存しましょう.\n",
"\n",
"```\n",
"円周率 3.1415926535\n",
"自然対数の底 2.7182818284\n",
"3次元最密充填の平均密度 0.74048\n",
"チャンパーノウン定数  0.12345678910\n",
"コープランド–エルデシュ定数 0.2357111317\n",
"```\n",
"\n",
"<font size=\"-1\">(よだんだよん) これらの定数の値はいずれも正確ではありません.適当な桁数で切り捨て/四捨五入した近似値です.</font>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"自分の作ったプログラム等でファイルを扱う場合,多くのプログラミング言語では,\n",
"\n",
"1. ファイルを開く\n",
"1. ファイルの内容を読み書きする\n",
"1. ファイルを閉じる\n",
"\n",
"という手順を踏んだプログラムを書きます.Python でも同様です."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ファイルから読み込む(ファイルからの入力)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ファイルを開くには,組み込み関数 `open()` を使います( https://docs.python.jp/3/library/functions.html#open ).\n",
"\n",
"例えば,次のようにすると,カレントディレクトリ(この Jupyter Notebook が動いている現在地(ディレクトリ))内のファイル `ex06constants.txt` を **読み込みモード** で開きます(モードの詳細については教科書参照).\n",
"\n",
"テキストファイルを扱う際には,その文字コードや改行の種類(改行の仕方は環境によって複数あるのです)を気にすることが必要になる場合があります.\n",
"以下の `open()` の3つ目の引数はそれに関係するものです.\n",
"その意味などについては,後述の「補足」を参照してください."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 1. ファイルを開く\n",
"f = open('ex06constants.txt', 'r', encoding='utf-8')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`open()` は,ファイルを開くことに成功した場合,戻り値として開いたファイルを指す **ファイルオブジェクト** というものを返します.\n",
"読み書き等は,このファイルオブジェクトのメソッドを利用して行います.試しに `readline()`メソッド(p.224)使ってみましょう."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 2. ファイルの内容を読み書きする\n",
"s = f.readline()\n",
"print(s)\n",
"s = f.readline()\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`readline()` は,1行文を読み込んでその内容を戻り値として返してくれます.その文字列には文末の改行文字も含まれているので,`print()`関数を使って出力すると上記のようになります(文字列中の改行文字を出力した後で`print()`も改行を出力するので)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"読み込みはここまでとして,ファイルを閉じることにしましょう. ファイルオブジェクトに対する `close()` メソッドを使います. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 3. ファイルを閉じる\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"さて,いったん閉じたファイルを再度開くとどうなるか,` #1. ファイルを開く` から順にもう一度実行してみましょう."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"結果は変わりませんね? モード `'r'` (読み込みモード)でファイルを `open()` すると,常にファイルの先頭から読み込みをはじめることになります."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ここで,`open()`に渡すファイル名を間違えた(存在しないファイル名を指定した)場合にどうなるか,試しておきましょう."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 存在しないファイル名を指定したら? \n",
"f = open('ex06constantsHOGE.txt', 'r', encoding='utf-8')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"テキストファイルを読み込むには上記のように `readline()` メソッドを使ってもよいのですが,次のようにファイルオブジェクトを直接 `for`文に渡してループさせる方が簡単です."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f = open('ex06constants.txt', 'r', encoding='utf-8')\n",
"for line in f: # f が指すファイルから1行ずつ読み込んだ内容を変数 line に代入してループ\n",
" print(line)\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ファイルへ書き込む(ファイルへの出力)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"次は,文字列をテキストファイルに書き込んでみましょう. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"S1 = 'hoge 12345 fuga '\n",
"S2 = 'ほげ〜ほげ〜 ほげほげ〜'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"新しく `'ex06hoge.txt'` というファイルを作って上記の2つの文字列を1行ずつ書き込むことにします."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"まず,`open()`関数の引数に `'w'` を指定して,**書き込みモード**でファイルを開きます.ここでも,3つ目の引数は文字コードの指定のためのものです(「補足」参照)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f = open('ex06hoge.txt', 'w', encoding='utf-8')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**書き込みモードで開く場合,ファイルが存在しなければ作成されます.存在していた場合,開いた瞬間に空になります**.\n",
"ファイル名の間違いやモードの間違いに気をつけましょう."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"読み込み同様,書き込みにもファイルオブジェクトに対するメソッドを使います.\n",
"例えば,`write()` メソッドを使うと,文字列をファイルに書き込めます. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f.write(S1 + '\\n')\n",
"f.write(S2 + '\\n')\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"この例では文字列 `S1` と `S2` の末尾に改行がありませんので,末尾に連結してから `write()` メソッドに渡してます."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ちゃんとファイルができたかどうか, `ex06hoge.txt` をエディタで開いて確認してみましょう."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 練習\n",
"\n",
"上記で作ったファイル `ex06hoge.txt` を読み込んでその内容を1行ずつ表示するプログラムを書きましょう."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# ここに ex06hoge.txt を読み込んで1行ずつ表示するコードを書く\n",
"\n",
"for line in :\n",
" print(line, end='') # こうすると,print() 自身が最後に改行を出力するのを抑制できる\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### with 文の使用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"上記の練習の答えのプログラムは,`with`文というものを使って次のように書くこともできます."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open('ex06hoge.txt', 'r', encoding='utf-8') as f:\n",
" for line in f:\n",
" print(line, end='')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`with`文については,p.340に載っています.`f.close()`がありませんが,書き忘れではなく,必要ありません.この書き方では,`open()`が成功した場合,`with`文のインデントブロックの実行を終えるタイミングで自動的にファイルが閉じられます.\n",
"\n",
"`with`文についてちゃんと説明するためには,**例外処理**というものを学ぶ必要があるのですが,この授業ではそこへは立ち入りません.ただし,実用的なプログラムを書くときには大事な話です(例えば,ファイルを開く際には,「(読み込みモードで開こうとしたが)ファイルが存在しない」とか「ファイルを作れない」といった場合への対処が必要).\n",
"興味のあるひとは,教科書p.335からのChapter10を参照してください.\n",
"\n",
"例は載せませんが,書き込みの場合も同様に書くことができます."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 補足いろいろ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. 文字コードの話\n",
"1. パスの話\n",
"1. バイナリモード\n",
"1. print でファイル出力"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(1) 「情報処理の基礎」で少し触れましたが,日本語の文字コードには複数の種類があります.\n",
"近年は,**UTF-8** というものが多く使われています.\n",
"Python3 は標準で UTF-8 を扱うようになっており,この授業の通りにインストール・設定した VSCode も UTF-8 がデフォルトです.\n",
"\n",
"なので,UTF-8で書かれたファイルを読み書きするために特別なことをする必要はないはずですが,Windowsの場合は,ファイルを開く際に文字コードの指定が必要なときがあります.\n",
"ここまで出てきた `open('hoge', 'r', encoding='utf-8')` のようなものの3つ目の引数は,「このファイルは `UTF-8` の文字コードで符号化されたものだよ」と指定しています.\n",
"macOSやLinuxではこの指定は不要ですが,あっても害はないはずです(違う文字コードのファイルを扱いたいときは別ですが).\n",
"\n",
"\n",
"余談ですが,Microsoft Windows は昔から,**Shift JIS** と俗称される独自の文字コードを使っており,他のOSとの間でのデータのやりとりの際は,それが原因で面倒なことになることがよくあります."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(2) これまでの例では `open()` の第1引数にファイル名を指定していましたが,実際にはディレクトリ名を含む **パス** (path) を書くことができます. 例えば, Linux や macOS で `/`(ルートディレクトリ)の中の `hoge` というディレクトリの中の `fuga` というディレクトリの中の `hena` というファイルを指定するなら, \n",
"```\n",
"open('/hoge/fuga/hena', 'r')\n",
"```\n",
"のように書けばok(こういうファイルのありかの指定は**絶対パス**というのでした).もちろん,\n",
"```\n",
"open('../hoge/hena', 'r')\n",
"```\n",
"のような指定の仕方(**相対パス**)も可能です."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(3) ここでは `open()` で指定するモードとして「読み込み(`'r'`)」 と「書き込み(`'w'`)」の2種類のみ説明しましたが,他にもいろいろあります(p.221参照).\n",
"画像や音声のようなデータを扱う際は,**バイナリモード**というもののお世話になるかもしれません.\n",
"ちなみに,p.220 や https://docs.python.jp/3/library/functions.html#open を読むとわかりますが,`open()` に第1引数のみ指定した場合, `'r'`を指定したのと同じになります."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(4) ここではファイルへ書き込む処理としてファイルオブジェクトの `write()` メソッドを使う例を示しましたが,`print()`関数のキーワード引数 `file` にファイルオブジェクトを指定する方法もあります(ついでに `with`文使う例にもしました).\n",
"\n",
"cf. https://docs.python.jp/3/library/functions.html#print"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open('ex06hoge.txt', 'w') as f:\n",
" print(S1, file=f)\n",
" print(S2, file=f)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.8.5"
},
"toc": {
"base_numbering": 1,
"nav_menu": {
"height": "146px",
"width": "258px"
},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "目次",
"title_sidebar": "Contents",
"toc_cell": true,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment