≪いっしょにPython≫ プログラマーの実験ノート
このページは,プログラム言語Pythonをこれから学ぼうと考えている筆者の備忘録です.
そこそこ調べて書いていますが,仕様を精密に調べたものではありません.どちらかと言えば,実装されたPython 3を使ってみてどうなったかということを中心に書いたものです.いわば,実験ノートの記録です.(2019.4.5,Python3.7.2に基づいて作成)
Pythonの練習には,
(1) IDLEというメニューから入って,>>>というプロンプトが表示される状態で使う場合
• 画面の上端がPython 3.7.x Shellとなっていて,2行目がFile, Edit, Shell, Debug, ...となっている
• 1行入力するたびに,エラーを確かめながら処理を進める,対話型インタプリタの形になっている
(2) IDLEというメニューから入って,左上端のFileをクリック→New Fileと進む場合
• 画面の上端がファイル名(初めはUntitled)となっていて,2行目がFile, Edit, format, Run, ...となっている
(3) Python 3.7.x という真っ黒なコマンドプロンプトの画面(ターミナルウィンドウ)から入るもの
の3通りが使えるが,以下は(2)のNew Fileから,テキストエディタを使って,プログラムを書く場合を考える.
1. ファイルの読み書き
(1) テキストファイルの書き込み
• テキストファイルに名前を付けて書き込むには,Pythonの組み込み関数(ビルドイン関数)open()とwrite()を使うのが簡単です.
• 以下において,解説はWindows上で動いているPythonを前提として行います.他の環境の方は,それぞれ読み替えてください.
• ファイル書き込みを行うには,いろいろな約束事がありますが,とりあえず自分が作業するために使うフォルダ(ディレクトリ)を決めて,その中のファイルは作業に失敗した場合に消えてしまっても構わないものだけにしておきましょう.(Program Filesのように空白文字を含むフォルダやマイドキュメントのように全角文字を含むフォルダでなく,c:/data/のように英字で簡単に書き込めるフォルダを作っておくとよいでしょう.ルートc:/などに直接書くのは避けた方がよいでしょう.)
【例 1.1.1】
→
• 別途,TeraPadとかメモ帳などのテキストエディタから該当のファイルの中身がどうなっているか確かめるとよい.なお,Pythonの開発環境に附属しているエディタからも読めるが,一般のエディタで読めるテキストファイルになっているということが確認できる方が,もっとうれしいはずです.
• s1は文字列の例.他の文章でもよいが,エンコードについてまだ説明していないので,半角英語だけで書かれた文字列でスタート.文字列を囲む引用符と同じもの(アポストロフィー)が文字列の中になる場合は要注意
• パソコン内のフォルダを表す文字として,スラッシュ(/)が使えます.円記号(\)を使う場合,文字列の中に書かれた円記号はエスケープ記号となるので,円記号(\)自体の文字を表すために,c:\\data\\test1.txtのように2つ重ねて書く必要がある.
• 入力と出力…あなたがパソコンを操作しているとき,キーボードやマウスを通じてパソコンに情報を送り,パソコンが処理した結果が画面に表示される.この場合において,あなたとパソコンとでは,主体と客体が逆になるが「コンピュータ関連の用語としては,パソコン(CPU)を主体として,パソコン(CPU)から見た立場で,用語の使い方が決められる」.すなわち,パソコンのシステムに情報が入ることを「入力」,パソコンから情報が出ることを「出力」と呼ぶ.
• 初期のコンピュータは,計算結果をプリンタに送って紙に印刷していたので紙くい虫と皮肉られたらしい.しかし,その後,モニタ画面に結果を表示することができるようになって,紙の無駄遣いは減った.このように,標準出力(特に出力先を指定しなかった場合の出力先)は,プリンタからモニタ画面に変わったということで,プリンタとモニタ画面はいずれも「出力専用」の装置です.
キーボードやマウスは入力専用の装置です.(キーボードやマウスにコンピュータの計算結果が出力されることはない)
• これに対して,ファイルやネットは入力に使う場合も,出力に使う場合もある.
• 自分のパソコン上のファイルの読み(入力),書き(出力)のいずれの場合も,open()という関数を使って,ストリーム(データの流れ)を制御するファイル・オブジェクトを得て,これを使う.
【書式】
オブジェクト名 = open(ファイル名, 'wt') …(1)
オブジェクト名.write(文字列) …(2)
print(文字列, file=オブジェクト名) …(2’)
オブジェクト名.close() …(3)
(解説)
(1) open()関数には,ファイル名に続いて,書き込みならwを,読み出しならrという引数を渡して,どちらのモードでファイルを開くかを指定します.もう1つ,テキストファイルならtをバイナリファイルならbも指定します.他にもありますが,とりあえずこの2×2通りが基本です.
普通,紙でできた本を開くだけなら,何も起こりませんが,コンピュータ上のファイルを書き込みモード(w)で開くと,実は,そのファイルは中身が全部消えます.
何もない所から書き込むので,ファイルの中身は新しく書き込んだ文字だけになります.
(2) ファイルの中では終端(End of File)の位置が管理されていて,write()メソッドにより,ファイルの終端に文字列が書き加えられると考えるとよいでしょう.
open()関数を使ってwモードでファイルを開いたとき,ファイルは0バイトになって,先頭位置にEOFがあります.そこで,文字列を1回書き込むと,文字列の最後の位置にEOFが来ます.だから,オブジェクト名.write(文字列)を2回行った場合,上書きされるのでなく,同じ文字列が2回書き込まれます.
なお,ファイル書き込みは,write()メソッドだけでなく,print()関数を使ってもできます.(次の例1.1.2)
(3) 作業が済んだら必ずファイルをclose()するようにします.
【例 1.1.2】
→
print()関数は,そのまま使うと標準出力としてモニター画面に出力しますが,この出力を別の装置,例えばファイルに振り向けることができる.そのためには,print()関数の第2引数として、file=***と書き,ここにファイル名を指定します.
この引数を省略した普通の使い方では,file=sys.stdoutとなって,標準出力のモニター画面に出力されています.
• キーボードから入力した文字を読み込むには,input()関数が使える.
• 文字列 = input(プロンプト)の形で,プロンプトを表示でき,入力されたものが文字列に代入され,Enterキーが押されたら終わる.
【例 1.1.3】
→
キーボードから,漢字やひらがな,カタカナなどの全角文字を入力するとShift_JISとかUTF-8など,どのエンコーディングで書くのかという問題が起こりますが,何も指定しなければ,そのプログラムを書いているシステムを参照して決まるようです.
(2) テキストファイルの読み込み
【書式】
オブジェクト名 = open(ファイル名, 'rt') …(1)
文字列名 = オブジェクト名.read(バイト数) …(2)
オブジェクト名.close() …(3)
(解説)
(1) ファイルを読み込むには,open()関数でファイル名に続いて,第2引数としてrというモードを指定する.第2引数は,省略されれば読み込みモード(r)になり,かつテキストファイル(t)になる.
オブジェクト名 = open(ファイル名) → open(ファイル名,'rt')
オブジェクト名 = open(ファイル名, 'r') → open(ファイル名,'rt')
(2) open()したファイルを文字列として読み込むには,read()メソッドを使う.ただし,引数無しで単にread()とすると,一度にファイル全体を読んでしまう.小さなファイルであることが分かっている場合は,それでも問題ないが,巨大なファイルの場合,作業用メモリが足りなくなるおそれがある.このような場合,read(バイト数)とすることにより,指定したサイズずつ読み出して,再度こちら側で組み立てるという方法もある.
(3) 作業が済んだら必ずファイルをclose()するようにします.
【例 1.2.1】
→
c:/data/test1.txtというテキストファイルがあれば,それを(全部)読み出し,画面に表示する.
(3) ファイル読み書きのモード
【ファイル内の現在位置を調べる,変更するメソッド】
• r+ モードのように,読み書きをする場合には,ファイル内での現在位置を知るとともに,目的地に移動することができると便利です.
• ファイルオブジェクト.tell()メソッドは,ファイル内で先頭からの現在位置をバイト単位で返します.
ファイルオブジェクト.tell()
• 次の例は'abcdefg'の7文字が書かれたテキストファイルを r+t モードで読み込んで,初めにtell()で現在位置を確認し,read()してからもう一度tell()で現在位置を確認したものです.
【例 1.3.6】
→
0 (先頭位置は0で示される)
7 (最後の文字gの前は6だから,その後ろは7になる)
• ファイルオブジェクト.seek(offset, whence)メソッドは,whenceで指定される位置からoffsetバイトの位置に移動指せる.
第2引数whenceは0, 1, 2のいずれかの数値のみ指定可能で,0(第2引数を省略したときも0になる)はファイルの先頭から,1は現在位置から,2はファイルの末尾からを表す.
ファイルオブジェクト.seek(offset, whence)
仕様上は,以上のようになっていますが,ファイルをテキストモードで開いた場合には,whenceが1,2の場合,offsetに指定できるのは0だけで,0以外の値を指定するとエラーになります.
seek(0,1)は現在位置を変更しないので,興味がないとすると,ファイルの末尾に移動するためにseek(0,2)を利用することはできる.なお,ファイルの読み出しができるモード(r,r+,a+)では,read()によってもファイルの末尾に移動できる.
ファイルの末尾に移動する場合を除けば,実際上使いやすいのは,ファイル内での移動は,第2引数を0にして(省略して)ファイル先頭からのバイト数(0または正の整数)をoffsetにする書き方であると考えられる.
ファイルオブジェクト.seek(offset)
• 次の例は'ABCDEFGHIJ'の10文字が書かれたテキストファイルを r+t モードで読み込んで,ファイルオブジェクト.seek()メソッドで移動し,書き込む動作をしたものです.
【例 1.3.7】
→
A1CDE2GHIJ になる
【テキストモードとバイナリモード】
t• ファイルに収められているデータを読み出すときに,文字列として読める形に直すことをエンコードといい,逆にファイルに保存するために文字列をバイト列に直すことをデコードという.
• ファイルを読み書きするときに,エンコード,デコードの変換を行うのがテキストモード(t)で,何も変換せずにそのまま読み書きするのがバイナリモード(b)の区別です.
• 例えば,「かなカナ漢字」という文字を含むファイルを,バイナリモードでそのまま読み出すと
b'\x82\xa9\x82\xc8\x83J\x83i\x8a\xbf\x8e\x9a'
となって,普通は読めませんが,テキストモードで読み出すと
かなカナ漢字
のように読めます.
• エンコードには,UTF-8,Shift_JIS, ASCIIなど様々な方式があり,エンコードとデコードが対応していなければ「文字化け」が起こります.しかし,ここでは初心者向けとして,テキストモード(t)で読み書きすれば,パソコンが自動的に調整してくれると覚え,その結果を利用するようにします.
b• しかし,それではバイナリモードは何に使うのかと疑問に思われるかもしれませんが,例えば画像データ,音声データのように文字で表せないデータや,WordやExcelで作られたファイルのようにテキスト以外に,様々な制御コードを使っているファイルでは,それらを読み書きするには,バイナリモードが必要になります.次の例は,c:/data/python_file3.pngという画像ファイルがあるときに,これを読み出して,c:/data/python_file4.pngという別名で保存する.(元のファイルも残る)
【ファイルの読み込みモード】
r• オブジェクト名 = open(ファイル名, 'r') は,ファイルを読み込み用に開くときに使う.その名前のファイルが存在しなければエラーになる.
• このモードで開いたときに,write()メソッドを用いて書き込み動作をすると,エラーになる.
• テキストモード(t),バイナリモード(b)が省略されれば,テキストモードで開かれる.
• ファイルが存在すれば,その先頭位置に移動し,read()メソッドが使われた場合,先頭位置から読み出すことになる.
→
• c:/data/test1.txtというテキストファイルの内容が,Where there is a will, there is a way.であるとき,その全部を表示する.
• open('c:/data/test1.txt'),open('c:/data/test1.txt','rt')はopen('c:/data/test1.txt','r')と同じ
r+• オブジェクト名 = open(ファイル名, 'r+') は,ファイルの読み込みも書き込みも行うときに使う.その名前のファイルが存在しなければエラーになる.
• テキストモード(t),バイナリモード(b)が省略されれば,テキストモードで開かれる.
• ファイルが存在すれば,その先頭位置に移動し,read()メソッドが使われた場合,先頭位置から読み出す.
• 読み書きともできるので,便利そうに見えるが,ファイル内の現在位置を正確に把握しないと,想定外のことが起こる.
→
'123DE'になる
→
'ABCDE123'になる
→
'1ゥなカナ漢字'になる
【ファイルの書き込みモード】 …≪既存ファイルは消える≫
w• オブジェクト名 = open(ファイル名, 'w') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,内容はすべて消えて0バイトのファイルになる.
• 新規書き込み,追加書き込みはできるが,読み出しはできない.
w+• オブジェクト名 = open(ファイル名, 'w+') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,内容はすべて消えて0バイトのファイルになる.
• 新規書き込み,追加書き込み,読み出しともできる.
【ファイルの追加書き込みモード】 …≪既存ファイルは変更できない≫
a• オブジェクト名 = open(ファイル名, 'a') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,その末尾に追加書き込みできる.(aはappendの意味)
• 既存のファイルに追加書き込みすることのみ可能で,読み込みはできない.
• 追加書き込みした部分の訂正・削除はできない.さらに追加することはできる.
a+• オブジェクト名 = open(ファイル名, 'a+') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,その末尾に追加書き込みできる.
• 既存の部分,追加書き込みした部分も含めて読み込みは可能だが,追加書き込みした部分の訂正・削除はできない.さらに追加することはできる.
【ファイルの排他的生成モード】 …≪既存ファイルがあれば開けない≫
x• オブジェクト名 = open(ファイル名, 'x') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,開けずエラーとなる.(xはXORの意味)
• 新規にファイルを生成した場合は,書き込みや追加書き込みはできる.読み込みはできない.
x+• オブジェクト名 = open(ファイル名, 'x+') は,そのファイル名のファイルがなければ,新しく作る.同名のファイルがあれば,開けずエラーとなる.
• 新規にファイルを生成した場合は,書き込み,追加書き込み,読み込み,訂正ともできる.
(以下,テキストモードを前提として)
■■ 沢山あるように見えるが ■■
(1) 「既存データを読みたい」「既存データを訂正したい」「データの追加もしたい」とき使えるのはr+だけ
w,w+は既存データがあれば消去する,x,x+は既存データがあれば開けられない.
rは書き込めない.a,a+は追加書き込みは可能だが,既存データは変更できない.
(2) 「既存データを安全に残して,データの追加だけしたい」とき使えるのは,a,a+
w,w+は既存データがあれば消去する,x,x+は既存データがあれば開けられない.
rは書き込めない.r+は既存データを変更できる.
a,a+は追加書き込みは可能だが,既存データは変更できない.a+は既存データも読めるところがaと違う.
(3) 新規ファイルを作成した場合でも,w,w+,x,x+ではtell()やseek()が使えない.
データの中身が,ABCDEの5文字から成るc:/data/test1.txtというファイルを読み出して,画面に表示した後,Bをpに書き換え,さらに末尾にqrを追加するには
→
• r+で開くと,読み出し,訂正,追加書き込みができる.
• 2番目の文字の前に移動するにはseek(1),末尾に移動するにはread()やseek(0,2)が使える.
(4) ファイルの自動的なclose()
• 作業が済んだファイルは必ず閉じなければならない.
• with文,try...finally文によってファイルを開くと,そのブロックが終了したときに,ファイルは自動的に閉じられるので安全になる.
• with文を用いたファイルのopen()と自動的なclose()
→ ABCDEp
• a+で開くと,現在位置はファイルの末尾になるので,そこで書き込めば追加書き込みになる.
• seek(0)は既存データも含めたファイルの先頭に移動するので,そこからread()すると全部読める.
• try..finally文を用いたファイルのopen()と自動的なclose()
→ ABCDEp
• tryを実行して,エラーが起こらない場合,特定のエラーコードが返される場合(except)に分けて,以後の処理を指定できる.
• finallyには,どの場合でも必ず行われる処理を書く.
○== メニューに戻る ==