7. 入力と出力—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/tutorial/inputoutput
移動先:案内検索

7。 入出力

プログラムの出力を表示する方法はいくつかあります。 データは、人間が読める形式で印刷することも、将来使用するためにファイルに書き込むこともできます。 この章では、いくつかの可能性について説明します。

7.1。 ファンシーな出力フォーマット

これまで、値を書き込む2つの方法に遭遇しました。式ステートメント印刷ステートメントです。 (3番目の方法は、ファイルオブジェクトのwrite()メソッドを使用することです。標準出力ファイルはsys.stdoutとして参照できます。 詳細については、ライブラリリファレンスを参照してください。)

多くの場合、スペースで区切られた値を単に印刷するよりも、出力のフォーマットをより細かく制御する必要があります。 出力をフォーマットする方法は2つあります。 最初の方法は、すべての文字列処理を自分で行うことです。 文字列のスライスと連結操作を使用して、想像できる任意のレイアウトを作成できます。 文字列型には、特定の列幅に文字列をパディングするための便利な操作を実行するいくつかのメソッドがあります。 これらについては、まもなく説明します。 2番目の方法は、 str.format()メソッドを使用することです。

string モジュールには、値を文字列に置き換えるさらに別の方法を提供する Template クラスが含まれています。

もちろん、1つの質問が残っています。値を文字列に変換するにはどうすればよいですか? 幸い、Pythonには任意の値を文字列に変換する方法があります。それを repr()または str()関数に渡します。

str()関数は、かなり人間が読める値の表現を返すことを目的としていますが、 repr()は、インタプリタが読み取ることができる表現を生成することを目的としています(または同等の構文がない場合は、SyntaxErrorを強制します)。 人間が消費するための特定の表現を持たないオブジェクトの場合、 str()repr()と同じ値を返します。 数値やリストや辞書などの構造などの多くの値は、どちらの関数を使用しても同じ表現になります。 特に、文字列と浮動小数点数には2つの異なる表現があります。

いくつかの例:

>>> 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...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print hellos
'hello, world\n'
>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

正方形と立方体のテーブルを作成する2つの方法は次のとおりです。

>>> for x in range(1, 11):
...     print repr(x).rjust(2), repr(x*x).rjust(3),
...     # Note trailing comma on previous line
...     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 の動作方法により、各列の間に1つのスペースが追加されました。デフォルトでは、引数の間にスペースが追加されます。)

この例は、文字列オブジェクトの 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.

'!s'str()を適用)および'!r'repr()を適用)を使用して、フォーマットする前に値を変換できます。

>>> 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

分割したくない非常に長いフォーマット文字列がある場合は、位置ではなく名前でフォーマットする変数を参照できると便利です。 これは、dictを渡し、角かっこ'[]'を使用してキーにアクセスするだけで実行できます。

>>> 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 = {'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.

詳細については、文字列フォーマット操作セクションを参照してください。


7.2。 ファイルの読み取りと書き込み

open()はファイルオブジェクトを返し、最も一般的にはopen(filename, mode)の2つの引数で使用されます。

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

最初の引数は、ファイル名を含む文字列です。 2番目の引数は、ファイルの使用方法を説明するいくつかの文字を含む別の文字列です。 モードは、ファイルの読み取りのみの場合は'r'、書き込みのみの場合は'w'(同じ名前の既存のファイルは消去されます)、 [ X153X]は、追加するファイルを開きます。 ファイルに書き込まれたデータはすべて自動的に最後に追加されます。 'r+'は、読み取りと書き込みの両方でファイルを開きます。 mode 引数はオプションです。 'r'は、省略した場合に想定されます。

Windowsでは、モードに追加された'b'がバイナリモードでファイルを開くため、'rb''wb''r+b'などのモードもあります。 Windows上のPythonは、テキストファイルとバイナリファイルを区別します。 テキストファイルの行末文字は、データの読み取りまたは書き込み時に自動的にわずかに変更されます。 このファイルデータの舞台裏での変更はASCIIテキストファイルには問題ありませんが、JPEGまたはEXEファイルのようなバイナリデータは破損します。 このようなファイルの読み取りと書き込みを行うときは、バイナリモードの使用に十分注意してください。 Unixでは、モードに'b'を追加しても問題はないため、すべてのバイナリファイルに対してプラットフォームに依存せずに使用できます。

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

このセクションの残りの例では、fというファイルオブジェクトがすでに作成されていることを前提としています。

ファイルの内容を読み取るには、f.read(size)を呼び出します。これにより、ある量のデータが読み取られ、文字列として返されます。 size はオプションの数値引数です。 size が省略されているか負の場合、ファイルの内容全体が読み取られて返されます。 ファイルがマシンのメモリの2倍の大きさである場合、それはあなたの問題です。 それ以外の場合は、最大で 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()
''

ファイルから行を読み取る場合は、ファイルオブジェクトをループできます。 これはメモリ効率が高く、高速で、単純なコードにつながります。

>>> for line in f:
        print line,

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

リスト内のファイルのすべての行を読み取りたい場合は、list(f)またはf.readlines()を使用することもできます。

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)を使用します。 位置は、オフセットを基準点に追加して計算されます。 基準点は、 from_what 引数によって選択されます。 from_what の値0はファイルの先頭から測定し、1は現在のファイル位置を使用し、2はファイルの末尾を参照ポイントとして使用します。 from_what は省略可能で、デフォルトは0で、ファイルの先頭を参照ポイントとして使用します。

>>> f = open('workfile', 'r+')
>>> f.write('0123456789abcdef')
>>> f.seek(5)      # Go to the 6th byte in the file
>>> f.read(1)
'5'
>>> f.seek(-3, 2)  # Go to the 3rd byte before the end
>>> f.read(1)
'd'

ファイルの処理が終了したら、f.close()を呼び出してファイルを閉じ、開いているファイルが使用していたシステムリソースを解放します。 f.close()を呼び出した後、ファイルオブジェクトを使用しようとすると自動的に失敗します。

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

ファイルオブジェクトを処理するときは、 with キーワードを使用することをお勧めします。 これには、途中で例外が発生した場合でも、スイートの終了後にファイルが適切に閉じられるという利点があります。 また、同等の try - finally ブロックを書き込むよりもはるかに短いです。

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

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


7.2.2。 で構造化データを保存する json

文字列は、ファイルへの書き込みとファイルからの読み取りが簡単にできます。 read()メソッドは文字列のみを返すため、数値にはもう少し手間がかかります。文字列は、'123'のような文字列を受け取る int()のような関数に渡す必要があります。 ]そしてその数値123を返します。 ネストされたリストや辞書など、より複雑なデータ型を保存する場合、手動での解析とシリアル化は複雑になります。

Pythonでは、複雑なデータ型をファイルに保存するためのコードをユーザーが常に作成およびデバッグするのではなく、 JSON(JavaScript Object Notation)と呼ばれる一般的なデータ交換形式を使用できます。 json と呼ばれる標準モジュールは、Pythonデータ階層を取得し、それらを文字列表現に変換できます。 このプロセスはシリアル化と呼ばれます。 文字列表現からデータを再構築することを逆シリアル化と呼びます。 シリアル化と逆シリアル化の間に、オブジェクトを表す文字列がファイルまたはデータに保存されているか、ネットワーク接続を介して離れたマシンに送信されている可能性があります。

ノート

JSON形式は、データ交換を可能にするために最近のアプリケーションで一般的に使用されています。 多くのプログラマーはすでにこれに精通しているため、相互運用性に適しています。


オブジェクトxがある場合は、次の簡単なコード行でそのJSON文字列表現を表示できます。

>>> import json
>>> json.dumps([1, 'simple', 'list'])
'[1, "simple", "list"]'

dumps()関数の別の変形である dump()は、単にオブジェクトをファイルにシリアル化します。 したがって、fが書き込み用に開かれたファイルオブジェクトである場合、次のことができます。

json.dump(x, f)

オブジェクトを再度デコードするには、fが読み取り用に開かれたファイルオブジェクトの場合:

x = json.load(f)

この単純なシリアル化手法ではリストと辞書を処理できますが、JSONで任意のクラスインスタンスをシリアル化するには、少し余分な労力が必要です。 json モジュールのリファレンスには、この説明が含まれています。

も参照してください

ピクル-ピクルモジュール

JSON とは異なり、 pickle は、任意に複雑なPythonオブジェクトのシリアル化を可能にするプロトコルです。 そのため、Pythonに固有であり、他の言語で記述されたアプリケーションとの通信には使用できません。 また、デフォルトでは安全ではありません。信頼できないソースからのピクルスデータを逆シリアル化すると、データが熟練した攻撃者によって作成された場合、任意のコードが実行される可能性があります。