目次

前のトピックへ

6. モジュール

次のトピックへ

8. エラーと例外

このページ

7. 入力と出力

プログラムから出力を行う方法がいくつかあります。データは人間が読める形で出力することも、将来使うためにファイルに書くこともできます。この章では、こうした幾つかの出力の方法について話します。

7.1. ファンシーな出力の書式化

これまでのところ、値を出力する二つの方法: 式文 (expression statement)print 文が出てきました。 (第三はファイルオブジェクトの write() メソッドを使う方法です。標準出力を表すファイルは sys.stdout で参照できます。詳細はライブラリリファレンスを参照してください。)

出力を書式化する際に、単に値をスペースで区切って出力するよりももっときめ細かな制御をしたいと思うことがあるでしょう。出力を書式化するには二つの方法があります。第一の方法は、全ての文字列を自分で処理するというものです。文字列のスライスや結合といった操作を使えば、思い通りのレイアウトを作成することができます。文字列オブジェクトは、文字列を指定されたカラム幅に揃えるための幾つかの便利なメソッドを提供しています。これらのメソッドについてはすぐ後で簡単に説明します。もうひとつの方法は str.format() メソッドを利用することです。

string モジュールの Template クラスは文字列中の値を置換する別の方法を提供しています。

もちろん、一つ問題があります。値をどうやって文字列に変換したらいいのでしょうか?幸運なことに、Python には値を文字列に変換する方法があります。値を repr()str() 関数に渡してください。

str() 関数は、値を表現するときに人間にとって読みやすい形式の文字列を返します。一方、 repr() は、インタプリタが読めるような (あるいは、等価な値を表現するための構文がない場合には SyntaxError を送出させる) 表現にするためのものです。人間が利用するための特別な表現をもたないオブジェクトでは、 str()repr() と同じ値を返します。数値や、リストや辞書などの構造体のような多くの値は、どちらの関数でも同じ表現になります。文字列と浮動小数点は特別で、二つの別個の表現となります。

下にいくつか例を挙げます。

>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1.0/7.0)
'0.142857142857'
>>> repr(1.0/7.0)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print s
The value of x is 32.5, and y is 40000...
>>> # 文字列への repr() はクォートとバックスラッシュが付加される。
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print hellos
'hello, world\n'
>>> # repr() の引数は Python オブジェクトの場合もある:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

以下に 2 乗と 3 乗の値からなる表を書く二つの方法を示します。

>>> for x in range(1, 11):
...     print repr(x).rjust(2), repr(x*x).rjust(3),
...     # 上の行の末尾のコンマに注意
...     print repr(x*x*x).rjust(4)
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

>>> for x in range(1,11):
...     print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

(最初の例で、各カラムの間のスペース一個は print の働きで追加されていることに注意してください。 print は引数間に常に空白を追加します。)

この例では、文字列の str.rjust() メソッドの使い方を示しています。 str.rjust() は文字列を指定された幅のフィールド内に右詰めで入るように、左に空白を追加します。同様のメソッドとして、 str.ljust()str.center() があります。これらのメソッドは何か出力を行うわけではなく、ただ新しい文字列を返します。入力文字列が長すぎる場合、文字列を切り詰めることはせず、ただ値をそのまま返します。この仕様のためにカラムのレイアウトが滅茶苦茶になるかもしれませんが、嘘の値が代わりに書き出されるよりはましです。(本当に切り詰めを行いたいのなら、全てのカラムに x.ljust(n)[:n] のようにスライス表記を加えることもできます。)

もう一つのメソッド、 str.zfill() は、数値文字列の左側をゼロ詰めします。このメソッドは正と負の符号を正しく扱います。

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'

str.format() メソッドの基本的な使い方は次のようなものです。

>>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
We are the knights who say "Ni!"

括弧とその中の文字(これをフォーマットフィールドと呼びます)は、 str.format() メソッドに渡されたオブジェクトに置換されます。括弧の中の数字は str.format() メソッドに渡されたオブジェクトの位置を表します。

>>> print '{0} and {1}'.format('spam', 'eggs')
spam and eggs
>>> print '{1} and {0}'.format('spam', 'eggs')
eggs and spam

str.format() メソッドにキーワード引数が渡された場合、その値はキーワード引数の名前によって参照されます。

>>> print 'This {food} is {adjective}.'.format(
...       food='spam', adjective='absolutely horrible')
This spam is absolutely horrible.

順序引数とキーワード引数を組み合わせて使うこともできます。

>>> print 'The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
...                                                    other='Georg')
The story of Bill, Manfred, and Georg.

str() を適応する '!s'repr() を適応する '!r' を使って、値をフォーマットする前に変換することができます。

>>> import math
>>> print 'The value of PI is approximately {}.'.format(math.pi)
The value of PI is approximately 3.14159265359.
>>> print 'The value of PI is approximately {!r}.'.format(math.pi)
The value of PI is approximately 3.141592653589793.

オプションの ':' とフォーマット指定子を、フィールド名の後ろに付けることができます。フォーマット指定子によって値がどうフォーマットされるかを制御することができます。次の例では、円周率πを、小数点以下3桁でまるめてフォーマットしています。

>>> import math
>>> print 'The value of PI is approximately {0:.3f}.'.format(math.pi)
The value of PI is approximately 3.142.

':' の後ろに整数をつけると、そのフィールドの最低の文字幅を指定できます。この機能は綺麗なテーブルを作るのに便利です。

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print '{0:10} ==> {1:10d}'.format(name, phone)
...
Jack       ==>       4098
Dcab       ==>       7678
Sjoerd     ==>       4127

もしも長い書式化文字列があり、それを分割したくない場合には、変数を引数の位置ではなく変数の名前で参照できるとよいでしょう。これは、辞書を引数に渡して、角括弧 '[]' を使って辞書のキーを参照することで可能です。

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print ('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
...        'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

table を ‘**’ 記法を使ってキーワード引数として渡す方法もあります。

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

全てのローカルな変数が入った辞書を返す組み込み関数 vars() と組み合わせると特に便利です。

str.format() による文字列フォーマットの完全な解説は、 書式指定文字列の文法 を参照してください。

7.1.1. 古い文字列フォーマット方法

% 演算しを使って文字列フォーマットをする方法もあります。これは、演算子の左側の sprintf() スタイルのフォーマット文字列に、演算子の右側の値を適用し、その結果の文字列を返します。例えば:

::
>>> import math
>>> print 'The value of PI is approximately %5.3f.' % math.pi
The value of PI is approximately 3.142.

str.format() は最近導入された機能なので、多くの Python のコードがまだ % 演算子を利用しています。ですが、古い方法はいつか削除されるかもしれないので、普通は str.format() を使うのが良いでしょう。

より詳しい情報は 文字列フォーマット操作 にあります。

7.2. ファイルを読み書きする

open() はファイルオブジェクトを返します。大抵、 open(filename, mode) のように二つの引数を伴って呼び出されます。

>>> f = open('/tmp/workfile', 'w')
>>> print f
<open file '/tmp/workfile', mode 'w' at 80a0960>

最初の引数はファイル名の入った文字列です。二つめの引数も文字列で、ファイルをどのように使うかを示す数個の文字が入っています。 mode は、ファイルが読み出し専用なら 'r' 、書き込み専用 (同名の既存のファイルがあれば消去されます) なら 'w' とします。 'a' はファイルを追記用に開きます。ファイルに書き込まれた内容は自動的にファイルの終端に追加されます。 'r+' はファイルを読み書き両用に開きます。 mode 引数は省略可能で、省略された場合には 'r' であると仮定します。

Windows では、 mode'b' を追加するとファイルをバイナリモードで開きます。したがって、 'rb', 'wb', 'r+b' といったモードがあります。 Windows 上で動くPython はテキストファイルとバイナリファイルを区別しています。テキストファイルでは、読み書きの際に行末文字が自動的に少し変更されます。この舞台裏でのファイルデータ変更は、ASCII でできたテキストファイルでは差し支えないものですが、 JPEGEXE ファイルのようなバイナリデータは破損してしまうことになるでしょう。こうしたファイルを読み書きする際にはバイナリモードを使うよう十分注意してください。 Unix では、 'b' を追加しても何も影響がないので、バイナリフォーマットを扱うためのプラットフォーム非依存な方法として利用できます。

7.2.1. ファイルオブジェクトのメソッド

この節の以降の例は、 f というファイルオブジェクトが既に生成されているものと仮定します。

ファイルの内容を読み出すには、 f.read(size) を呼び出します。このメソッドはある量のデータを読み出して、文字列として返します。 size は省略可能な数値引数です。 size が省略されたり負の数であった場合、ファイルの内容全てを読み出して返します。ただし、ファイルがマシンのメモリの二倍の大きさもある場合にはどうなるかわかりません。 size が負でない数ならば、最大で size バイトを読み出して返します。ファイルの終端にすでに達していた場合、 f.read() は空の文字列 ("") を返します。

>>> f.read()
'This is the entire file.\n'
>>> f.read()
''

f.readline() はファイルから 1 行だけを読み取ります。改行文字 (\n) は読み出された文字列の終端に残ります。改行が省略されるのは、ファイルが改行で終わっていない場合の最終行のみです。これは、戻り値があいまいでないようにするためです; f.readline() が空の文字列を返したら、ファイルの終端に達したことが分かります。一方、空行は '\n' 、すなわち改行 1 文字だけからなる文字列で表現されます。

>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''

f.readlines() は、ファイルに入っているデータの全ての行からなるリストを返します。省略可能な引数 sizehint が指定されていれば、ファイルから指定されたバイト数を読み出し、さらに一行を完成させるのに必要なだけを読み出して、読み出された行からなるリストを返します。このメソッドは巨大なファイルを行単位で効率的に読み出すためによく使われます。未完成の行が返されることはありません。

>>> f.readlines()
['This is the first line of the file.\n', 'Second line of the file\n']

行を読む別のアプローチは、ファイルオブジェクトについてループをおこなうことです。これは省メモリで、速く、コードがよりシンプルになります。

>>> for line in f:
        print line,

This is the first line of the file.
Second line of the file

この方法はシンプルですが細かなコントロールをすることができません。行バッファを管理する方法が異なるので、これらを混在させて使うことはできません。

f.write(string) は、 string の内容をファイルに書き込み、 None を返します。

>>> f.write('This is a test\n')

文字列以外のものを出力したい場合、まず文字列に変換してやる必要があります。

>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)

f.tell() は、ファイルオブジェクトが指しているあるファイル中の位置を示す整数を、ファイルの先頭からのバイト数で図った値で返します。ファイルオブジェクトの位置を変更するには、 f.seek(offset,  from_what) を使います。ファイル位置は基準点 (reference point) にオフセット値 offset を足して計算されます。参照点は from_what 引数で選びます。 from_what の値が 0 ならばファイルの先頭から測り、 1 ならば現在のファイル位置を使い、2 ならばファイルの終端を参照点として使います。 from_what は省略することができ、デフォルトの値は 0 、すなわち参照点としてファイルの先頭を使います。

>>> f = open('/tmp/workfile', 'r+')
>>> f.write('0123456789abcdef')
>>> f.seek(5)     # ファイルの第6バイトへ行く
>>> f.read(1)
'5'
>>> f.seek(-3, 2) # 終端から前へ第3バイトへ行く
>>> f.read(1)
'd'

ファイルが用済みになったら、 f.close() を呼び出してファイルを閉じ、ファイルを開くために取られていたシステム資源を解放します。 f.close() を呼び出した後、そのファイルオブジェクトを使おうとすると自動的に失敗します。

>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file

ファイルオブジェクトを扱うときに with キーワードを使うのは良い習慣です。 with を使うと、処理中に例外が発生しても必ず最後にファイルを閉じることができます。同じことを try-finally を使って書くよりずっと簡潔に書けます。

>>> with open('/tmp/workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True

ファイルオブジェクトには、他にも isatty()truncate() といった、あまり使われないメソッドがあります。ファイルオブジェクトについての完全なガイドは、ライブラリリファレンスを参照してください。

7.2.2. pickle モジュール

文字列をファイルに読み書きするのは簡単にできます。数値だとほんのわずかに手間が増えます。というのは、 read() は文字列だけを返すので、 '123' のような文字列を受け取って、その数値 123 を返す int() のような関数に文字列を渡してやらなければならないからです。ところが、リストや辞書、クラスのインスタンスのように、もっと複雑なデータ型を保存したいなら、事態はもっと複雑になります。

複雑なデータ型を保存するためのコードを毎回毎回書いてデバッグする代わりに、 Python では pickle という標準モジュールを用意しています。 pickle は驚くべきモジュールで、ほとんどどんな Python オブジェクトでも (ある形式の Python コードでさえも!) 受け取って文字列表現へ変換できます。この変換過程は pickling (ピクルス (漬物) 化、以降 pickle 化) と呼ばれます。文字列表現からオブジェクトを再構成する操作は unpickling (逆 pickle 化) と呼びます。 pickle 化してから unpickle 化するまでの間、オブジェクトを表現する文字列は、ファイルやデータに保存したり、ネットワーク接続を介して離れたマシンに送信したりできます。

オブジェクト x と、書込み用に開かれているファイルオブジェクト f があると仮定すると、オブジェクトを pickle 化する最も簡単な方法は、たった一行のコードです。

pickle.dump(x, f)

逆 pickle 化して再びオブジェクトに戻すには、 f を読取り用に開かれているファイル・オブジェクトと仮定して、

x = pickle.load(f)

とします。

(pickle / 逆 pickle 化にはいくつか方法があり、たくさんのオブジェクトを pickle 化したり、 pickle 化されたデータをファイルに書きたくないときに使われます。完全なドキュメントについては、ライブラリリファレンスの pickle を調べてください。)

pickle は、 Python のオブジェクトを保存できるようにし、他のプログラムや、同じプログラムが将来起動されたときに再利用できるようにする標準の方法です。技術的な用語でいうと persistent (永続性) オブジェクトです。 pickle はとても広範に使われているので、 Python 拡張モジュールの多くの作者は、行列のような新たなデータ型が正しく pickle / 逆 pickle 化できるよう気をつけています。