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

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

7。 入出力

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

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

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

多くの場合、スペースで区切られた値を単に印刷するよりも、出力のフォーマットをより細かく制御する必要があります。 出力をフォーマットする方法はいくつかあります。

  • 形式の文字列リテラルを使用するには、開始引用符または三重引用符の前にfまたはFで文字列を開始します。 この文字列内で、変数またはリテラル値を参照できる{文字と}文字の間にPython式を記述できます。

    >>> year = 2016
    >>> event = 'Referendum'
    >>> f'Results of the {year} {event}'
    'Results of the 2016 Referendum'
  • 文字列の str.format()メソッドは、より多くの手動作業を必要とします。 {}を使用して、変数が置換される場所をマークし、詳細なフォーマットディレクティブを提供できますが、フォーマットする情報も提供する必要があります。

    >>> yes_votes = 42_572_654
    >>> no_votes = 43_132_495
    >>> percentage = yes_votes / (yes_votes + no_votes)
    >>> '{:-9} YES votes  {:2.2%}'.format(yes_votes, percentage)
    ' 42572654 YES votes  49.67%'
  • 最後に、文字列のスライス操作と連結操作を使用して、想像できる任意のレイアウトを作成することにより、すべての文字列処理を自分で行うことができます。 文字列型には、特定の列幅に文字列をパディングするための便利な操作を実行するいくつかのメソッドがあります。

派手な出力は必要ないが、デバッグ目的でいくつかの変数をすばやく表示したい場合は、 repr()または str()を使用して任意の値を文字列に変換できます。関数。

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

いくつかの例:

>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1/7)
'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'))"

string モジュールには Template クラスが含まれており、$xなどのプレースホルダーを使用して値を文字列に置き換える別の方法を提供しますが、書式設定の制御がはるかに少なくなります。

7.1.1。 フォーマットされた文字列リテラル

フォーマットされた文字列リテラル(略してf文字列とも呼ばれます)を使用すると、文字列の前にfまたはFを付けて式を記述することにより、Python式の値を文字列内に含めることができます。 {expression}として。

オプションのフォーマット指定子は、式の後に続けることができます。 これにより、値のフォーマット方法をより細かく制御できます。 次の例では、円周率を小数点以下3桁に丸めます。

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

':'の後に整数を渡すと、そのフィールドの幅は最小文字数になります。 これは、列を整列させるのに役立ちます。

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

他の修飾子を使用して、フォーマットする前に値を変換できます。 '!a'ascii()を適用し、'!s'str()を適用し、'!r'repr()を適用します]:

>>> animals = 'eels'
>>> print(f'My hovercraft is full of {animals}.')
My hovercraft is full of eels.
>>> print(f'My hovercraft is full of {animals!r}.')
My hovercraft is full of 'eels'.

これらのフォーマット仕様のリファレンスについては、フォーマット仕様ミニ言語のリファレンスガイドを参照してください。


7.1.2。 String format()メソッド

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.

分割したくない非常に長いフォーマット文字列がある場合は、位置ではなく名前でフォーマットする変数を参照できると便利です。 これは、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()と組み合わせると特に便利です。

例として、次の行は、整数とその平方および立方体を与える、きちんと整列された列のセットを生成します。

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

str.format()を使用した文字列フォーマットの完全な概要については、フォーマット文字列構文を参照してください。


7.1.3。 手動文字列フォーマット

これは、手動でフォーマットされた同じ正方形と立方体のテーブルです。

>>> for x in range(1, 11):
...     print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
...     # Note use of 'end' 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

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'

7.1.4。 古い文字列のフォーマット

% o perator(モジュロ)は、文字列のフォーマットにも使用できます。 'string' % valuesを指定すると、string%のインスタンスは、valuesの0個以上の要素に置き換えられます。 この操作は、一般に文字列補間として知られています。 例えば:

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

詳細については、 printfスタイルの文字列フォーマットセクションを参照してください。


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

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

>>> f = open('workfile', 'w')

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

通常、ファイルはテキストモードで開かれます。つまり、特定のエンコーディングでエンコードされた文字列をファイルとの間で読み書きします。 エンコーディングが指定されていない場合、デフォルトはプラットフォームに依存します( open()を参照)。 モードに追加された'b'は、ファイルをバイナリモードで開きます。これで、データはバイトオブジェクトの形式で読み書きされます。 このモードは、テキストを含まないすべてのファイルに使用する必要があります。

テキストモードでは、読み取り時のデフォルトは、プラットフォーム固有の行末(Unixでは\n、Windowsでは\r\n)を\nに変換することです。 テキストモードで書き込む場合、デフォルトでは、\nの出現箇所がプラットフォーム固有の行末に変換されます。 このファイルデータの舞台裏での変更はテキストファイルには問題ありませんが、JPEGまたはEXEファイルのようなバイナリデータは破損します。 このようなファイルの読み取りと書き込みを行うときは、バイナリモードの使用に十分注意してください。

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

>>> with open('workfile') as f:
...     read_data = f.read()

>>> # We can check that the file has been automatically closed.
>>> f.closed
True

with キーワードを使用していない場合は、f.close()を呼び出してファイルを閉じ、ファイルで使用されているシステムリソースをすぐに解放する必要があります。

警告

withキーワードを使用せずにf.write()を呼び出すか、f.close() 可能性があるを呼び出すと、f.write()の引数がディスクに完全に書き込まれません。 、プログラムが正常に終了した場合でも。


with ステートメントまたはf.close()の呼び出しによってファイルオブジェクトが閉じられた後、ファイルオブジェクトの使用は自動的に失敗します。

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

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

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

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

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

>>> for line in f:
...     print(line, end='')
...
This is the first line of the file.
Second line of the file

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

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

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

他のタイプのオブジェクトは、書き込む前に、文字列(テキストモード)またはバイトオブジェクト(バイナリモード)のいずれかに変換する必要があります。

>>> value = ('the answer', 42)
>>> s = str(value)  # convert the tuple to string
>>> f.write(s)
18

f.tell()は、ファイル内のファイルオブジェクトの現在の位置を示す整数を返します。これは、バイナリモードの場合はファイルの先頭からのバイト数で表され、テキストモードの場合は不透明な数値で表されます。

ファイルオブジェクトの位置を変更するには、f.seek(offset, whence)を使用します。 位置は、オフセットを基準点に追加して計算されます。 基準点は whence 引数によって選択されます。 whence の値が0の場合、ファイルの先頭から測定され、1は現在のファイル位置を使用し、2はファイルの末尾を参照ポイントとして使用します。 whence は省略可能で、デフォルトは0で、ファイルの先頭を参照ポイントとして使用します。

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

テキストファイル(モード文字列でbなしで開かれたファイル)では、ファイルの先頭を基準にしたシークのみが許可されます(seek(0, 2)でファイルの最後をシークする場合を除く)。有効なオフセット値は、f.tell()から返される値、つまりゼロのみです。 その他の offset 値は、未定義の動作を生成します。

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


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

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

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

ノート

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


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

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

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

json.dump(x, f)

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

x = json.load(f)

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

も参照してください

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

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