file I/O, with 構文
ファイルの使い方は、詳しくはpython の公式文書を参照してください。
今回は、ファイル読み書きをするプログラム例を用いて簡単な事例説明をおこないます。
バイトで読書き
ファイルはバイト列なので、まずはバイト列のまま処理してみます。 ここではファイルコピーをおこなうreadwrite_file_in_bytes()を説明しますね。
まず、ファイルを開いて、bytes 型の data を取得するのはこんな感じでOK.
with open(filename, 'rb') as file_in:
while True:
data: bytes = file_in.read(BUF_SIZE)
if not data: # ファイルを読み終わったら終了
break
print(data) # bytes を表示してみる
with openでファイルを開くrbは、rがファイルの read を意味し、bは binary mode を意味する- 開いたファイルは
file_inでアクセス可能 - 後述するように、
withブロックから抜けた際、ファイルを閉じてくれる
file_in.read(BUF_SIZE)で、指定サイズのデータを取得
一方で、ファイルへの書込みはこんな感じの操作になります。
with open(out_filename, 'wb') as file_out:
# loop
file_out.write(data)
with openだけど、今度はwbで書込み+binary モードfile_out.write(data)で、dataを書込み
なので、file copy だと、こんな感じ。
def readwrite_file_in_bytes(filename, out_filename):
# ファイルを開いて
with open(filename, 'rb') as file_in:
with open(out_filename, 'wb') as file_out:
print('Start: readwrite_file_in_bytes')
while True:
# ファイルの中身を
data: bytes = file_in.read(BUF_SIZE)
if not data: # ファイルを読み終わったら終了
print('Done: readwrite_file_in_bytes')
break
print(data)
file_out.write(data)
テキストを1行ずつ読書き
今度は、テキストファイルを読書きしてみましょう。 いくつかやり方があるのですが、素直に1行ずつ読書きする例(readwrite_file_in_lines()だけ、説明しておきます。
ファイルを読む部分はこれぐらい。
with open(filename, 'r', encoding='utf-8') as file_in:
for line in file_in: # line は改行含む
print(line) # なので、改行x2 出力される
with openでファイルを開く- 今度は text mode で読むので
rbじゃなくrモード - テキストファイルを開く際、文字コード指定をおこなう (
encoding='utf-8')- python の関数呼び出し引数に関する解説は、こちら
- 今度は text mode で読むので
for line in file_in:で、file_inから1行ずつデータを取得してループ実行- 取得したデータには
line変数でアクセス可能 lineには、改行も含まれている
- 取得したデータには
一方で、書く方は、こんな感じ
with open(out_filename, 'w', encoding='utf-8') as file_out:
# loop
file_out.write(line)
with openだけど、wモード、つまり書込み+ text modefile_out.write(data)で、lineを書込み
ってことで、1行ずつファイルコピーするなら、こんな感じ。
def readwrite_file_in_lines(filename, out_filename):
# ファイルを開いて
print('Start: readwrite_file_in_lines')
with open(filename, 'r', encoding='utf-8') as file_in:
with open(out_filename, 'w', encoding='utf-8') as file_out:
for line in file_in: # line は改行含む
print(line) # なので、改行x2 出力される
file_out.write(line)
print('Done: readwrite_file_in_lines')
with 構文
I/O では、stream を開いて、一連の処理をした後で stream を閉じる必要があります。
ちょっと注意すべきは、プログラムが途中で例外などで途中終了する場合も、stream を閉じないといけないことです。
with 構文をつかってファイルを開いたり、ネットワークソケットを開いたりすると、
正常終了か例外による終了かに関わらず、with で開いたファイル・ソケットを自動で閉じてくれます。
with open(out_filename, 'w', encoding='utf-8') as file_out:
# loop
# ネットワーク経由でデータ取得。接続切れたら例外発生!
line = RECEIVE_DATA_FROM_NETWORK()
file_out.write(line)
今回はあまり取り上げませんが、python でも例外の仕組みがあります。ファイル操作に失敗した場合、例外が起きるのですが、その場合の処理が書けるのです。 例えばこんな感じ。
file_in = open(filename, 'rb')
try:
while True:
data = file_in.read(BUFSIZE)
if not data:
break
sock.sendall(data)
except Exception as excep:
# handle が書きたい場合
finally:
file_in.close()
file の open, close 処理も含めて、明示的に書いています。
まあでも、単にファイルを開いて、例外の有無にかかわらずブロック終了時に閉じるってだけなら、
with 構文の方がはるかにシンプルにプログラムが書けますよね。