kick the base

Houdiniと、CG技術と、日々のこと。

Python: ランダムなファイル名を持つテキストファイルを複数作成する02 -ファイル操作と文字列の書式化操作

前回はPythonの__name__for文についてお話しました。今回はPythonのファイル操作と文字列の書式化操作についてお話します。

環境

  • OS X 10.11.6
  • Python 3.4.4

最終的なコード

今回は9・10行目の説明に当たります。

ファイル操作

ファイルの読み込み

まずは最も基本的な読み込みから見ていきましょう。実際のコードではwith文を使っていますが、まずは泥臭い方法から。

下記のようなファイル構成でfile_open.pyを実行します。

.
├── file_open.py
└── sample.txt

file_open.pyは下記の通りです。

f = open('sample.txt', 'r')
lines = f.read()
print(lines)
f.close()

出力結果はsample.txtの中身を表示します。

$ python file_open.py
This is sample.

ここからはPythonコードを一行ずつ見ていきます。

1行目

f = open('sample.txt', 'r')

ファイルを開き、取得したファイルオブジェクトを変数fに代入します。第二引数はモードと呼ばれ、どのようにファイルを扱うかを指定します。*1

モード 意味
r readを意味し、読み込みモードで開く
w writeを意味し、書き込みモードで開く
a appendを意味し、追加書き込みモードで開く

実際はもっと多くのモードがありますが割愛します

ちなみにデフォルトは読み込みモードなので、第二引数を省略した場合自動的に読み込みモードになります。つまり本コードはf = open('sample.txt')としてもOKです。

2行目

lines = f.read()

readメソッドでファイルオブジェクトからテキストを読み取ります。*2

読み取った文字列を変数linesに代入します。

3行目

print(lines)

読み取った文字列を出力しているだけです。

4行目

f.close()

ファイルを閉じます。

openで開いたファイルは、使い終わったら必ずcloseするようにしましょう。

なぜこんなめんどくさい仕組みになっているのかというと、Pythonはファイルを開くためのシステムリソースを確保しており、ファイルを開き続けると限界に達し、それ以上ファイルを開けなくなってしまうからです。

しかしファイルを閉じるのを忘れないなんていう解決方法はナンセンスです。人間がそこを気にするのはベターな解決法とはいえませんね。そこで、最初に出てきたwith式を使う方法が用意されています。

with式で書き直す

with open('sample.txt', 'r') as f:
    lines = f.read()
    print(lines)

with式を使えばブロックを抜けたタイミングで勝手にファイルを閉じてくれます。処理中に例外が発生してもファイルは閉じてくれるところが優秀です。*3

with open( ... ) as ファイルオブジェクト:
    ファイル操作

このカタチを覚えてしまいましょう。

ファイルを書き込む

例のごとくまずはopencloseで行ってみましょう。

f = open('test.txt', 'w')
f.write('New text.')
f.close()

なんとなく意味はわかると思いますが、解説を続けます。

1行目

f = open('test.txt', 'w')

第一引数のファイルが存在していたら上書きを、存在していなかったらファイルを作成します。第二引数で書き込みモードを指定します。

2行目

f.write('New text.')

ファイル内に引数の文字列を書き込みます。

3行目

f.close()

ファイルを閉じます。

with式で書き直す

with open('test.txt', 'w') as f:
    f.write('New text.')

もう説明不要ですね。読み込みと全く同じ形式です。

文字列の書式化操作

Pythonには古くから使われている%形式の文字列フォーマット操作というのもあるのですが、ここではPython2.6から使用可能になったformatメソッドを用いて説明していきます。

順を追って見ていきましょう。

文字列の連結

name = 'めんたいこ'
print('私の名前は' + name + 'です')

非常にシンプルなコードですね。'めんたいこ'という文字列を変数nameに代入し、文字列と連結しています。

実行すると出力結果は

私の名前はめんたいこです

となります。ここまではOKですね。

formatメソッドによって書き換え

書き直したコードはこんな感じになります。

name = 'kickbase'
print('私の名前は{}です'.format(name))

'{}が入っている文字列'.formmat({}に入れたい値)

これがformatメソッドの形式です。ちなみに{}は以下のように複数個扱うことができます。{}が出てきた順番にformatメソッドの引数が入っていきます。*4

name = 'めんたいこ'
print('私の名前は{}です。TwitterIDは{}です'.format(name, 'kickbase'))

ん〜。なんだか書き換える前のほうが分かりやすかったような気がします。

しかし、勿論便利だからこのような機能があるわけで、以下ではその紹介をします。

文字連結におけるエラー

こちらを実行してみましょう。エラーが発生します。

age = 18
print('私の名前はめんたいこ、' + age + '歳です')

エラーはTypeError: Can't convert 'int' object to str implicitlyとなっていて、

型エラー: 数値は文字列に変換できませんという意味ですね。*5

こちらをformatメソッドで書き換えてみましょう。

formatメソッドによって書き換え

今度はどうでしょうか。

age = 18
print('私の名前はめんたいこ、{}歳です'.format(age))

実行するとエラーを出すことなく、私の名前はめんたいこ、18歳ですと意図通りに出力されました。

このように、formatメソッドを使うと型を意識しなくて良いというメリットがあります。便利なのでぜひ使っていってください。

まとめ

今回はPythonのファイル操作と文字列の書式化操作についてお話しました。ふたつの話題を話すだけでも結構な分量になってしまいましたが、まだ内包表記とモジュールの使い方が控えています。頑張っていきましょう。

*1:第三引数にはエンコード指定が入りますがここでは割愛します

*2:読み込まれるのは単純な文字列なので、str型です

*3:try-finallyを使うより断然スマートに書けます

*4:順番を変更したり、値を加工したりもできますが、今回は割愛します

*5:JavaScriptでは暗黙の型変換というやつで、数値と文字列はエラーも出さずしれっと結合されます。これが良い仕様かどうかはさておいて、違いがあるというのは知っておいて損はないかと思います