[解決!Python]print関数でファイルに書き込みを行うには解決!Python

print関数ではfileパラメーターにファイルオブジェクトを指定することで、ファイルへテキストを出力できる。その方法とwriteメソッドとの違いなどについて紹介する。

» 2023年11月14日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

filename = 'sample.txt'

with open(filename, 'w') as f:
    print('hello', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)  # hello

# リストの書き込み
l0 = ['1', '2', '3']
with open(filename, 'w') as f:
    print(l0, file=f)  # 引数はstr関数と同様に文字列化される

with open(filename) as f:
    contents = f.read()
    print(contents)  # ['1', '2', '3']

l1 = eval(contents)  # 書き込んだ内容を読み込んでeval関数でオブジェクトに復元
print(type(l1))  # <class 'list'>
print(l1)  # ['1', '2', '3']

# リストの内容をCSV形式で書き込む
l0 = [1, 2, 3]

result = ', '.join([str(x) for x in l0])
print(result)  # 1, 2, 3

with open(filename, 'w') as f:
    f.write(result)

with open(filename) as f:
    contents = f.read()
    print(contents)  # 1, 2, 3

print(*l0, sep=', '# 1, 2, 3

with open(filename, 'w') as f:
    print(*l0, sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)  # 1, 2, 3

# リストのリストをファイルに書き込む(writeメソッドを使用)
l0 = [[1, 2, 3], [4, 5, 6]]

result = ''
with open(filename, 'w') as f:
    for l in l0:
        result += ', '.join([str(x) for x in l]) + '\n'
    f.write(result)

with open(filename, 'w') as f:
    for l in l0:
        result = ', '.join([str(x) for x in l]) + '\n'
        f.write(result)

with open(filename, 'w') as f:
    result = []
    for l in l0:
        result.append(', '.join([str(x) for x in l]) + '\n')
    #result = [', '.join([str(x) for x in l]) + '\n' for l in l0]
    f.writelines(result)

with open(filename) as f:
    contents = f.read()
    print(contents)

# リストのリストをファイルに書き込む(print関数を使用)
l0 = [[1, 2, 3], [4, 5, 6]]

with open(filename, 'w') as f:
    for l in l0:
        print(*l, sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)

# 文字列はシングルクオートで囲みたいという場合は一手間が必要になる
l0 = [['1', '2', '3'], [4, 5, 6]]
with open(filename, 'w') as f:
    for l in l0:
        print(*l, sep=', ', file=f)
        print(*[repr(x) for x in l], sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)
# 出力結果:
#1, 2, 3
#'1', '2', '3'
#4, 5, 6
#4, 5, 6


print関数によるファイルへの書き込み

 print関数はコンソール(標準出力)へのテキスト出力によく使われるが、ファイルをオープンして、それをfileパラメーターに指定することで、ファイルにテキストを出力するのにも使える。

 以下は簡単な例だ。

filename = 'sample.txt'

with open(filename, 'w') as f:
    print('hello', file=f)


 この例は「sample.txt」という名前のファイルを書き込みモードでオープンし、そこにprint関数で書き込みを行っている。open関数でオープンしたファイルに対応するファイルオブジェクトをprint関数のfileパラメーターに渡している点に注目されたい。

 このファイルを読み込みモードでオープンして、その内容を確認するコードを以下に示す。

with open(filename) as f:
    contents = f.read()
    print(contents)  # hello


 コメントに示したように、書き込んだテキストが表示されるはずだ。

 print関数では引数に指定した位置引数(キーワード引数でないもの)は全てstr関数と同様な文字列化が行われて、デフォルトでは標準出力へ、あるいはfileパラメーターに指定したファイルやインメモリのテキストストリームなどへ出力される。そのため、リストを何も考えることなしにテキストファイルに出力することも可能だ。文字列以外のオブジェクトをテキストファイルに出力しようと思ったら、通常は何らかの形でそれらを文字列化する必要があるが、print関数なら、そうした処理に頭を悩ませる必要がなくなるかもしれない(逆にバイナリファイルにprint関数で出力することはできない)。

 例えば、リストをファイルに出力したいとしよう。

l0 = ['1', '2', '3']
with open(filename, 'w') as f:
    print(l0, file=f)  # 引数はstr関数と同様に文字列化される

with open(filename) as f:
    contents = f.read()
    print(contents)  # ['1', '2', '3']


 最初のwith文ではprint関数にリストをそのまま引き渡している。今述べたように、このリストオブジェクトは文字列化されて、出力先(この場合はsample.txtファイル)へと送られる。この結果、print関数が標準出力に書き出すのと同じ内容がテキストファイルに書き込まれる。

 場合によっては、次のように書き込んだ内容をテキストファイルから読み込んで、それを基にオブジェクトを復元することも可能だ。

l1 = eval(contents)  # 書き込んだ内容を読み込んでeval関数でオブジェクトに復元
print(type(l1))  # <class 'list'>
print(l1)  # ['1', '2', '3']


 この例では、テキストファイルに書き込まれた「['1', '2', '3']」からリストオブジェクトを復元している(ただし、そうした使い方を考えるのであればpickleモジュールなどの使用を考慮すべきだろう)。

 オブジェクトをそのままの形でテキストファイルに書き込むのではなく、例えば、リストの要素をCSV形式でファイルに出力するといったときにもprint関数を使うと楽ができるかもしれない。

 以下は、ファイルオブジェクトのwriteメソッドでリストの要素をCSV形式で書き込むコード例だ。

l0 = [1, 2, 3]

result = ', '.join([str(x) for x in l0])
print(result)  # 1, 2, 3

with open(filename, 'w') as f:
    f.write(result)

with open(filename) as f:
    contents = f.read()
    print(contents)  # 1, 2, 3


 まずテキストファイルへ書き込めるのはテキストだけなので、リストの内容を文字列化する必要がある。そのため、まず文字列のjoinメソッド(とstr関数)を使って、リストの要素を文字列にする。joinメソッドでは区切り文字としてカンマを指定することで、CSV形式の文字列が得られる。そして、これをwriteメソッドで書き込む。

 これに対して、print関数ではキーワード引数以外の位置引数は全て文字列化された上で出力先へ送られる。また、それらを区切る文字はsepパラメーターで指定できる。

print(*l0, sep=', '# 1, 2, 3


 この例はサンプルのリストを展開してprint関数に渡し、それらがカンマ区切りで表示されるようにしている。結果、「1, 2, 3」が出力されている。

 後はファイルをfileパラメーターに指定すれば、ファイルにCSV形式で出力ができるだろう。以下に例を示す。

with open(filename, 'w') as f:
    print(*l0, sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)  # 1, 2, 3


 最初のwith文ではファイルをオープンして、上で見たようにリストの要素を展開してprint関数に渡し、区切り文字に', 'を指定している。次のwith文ではその内容を確認しているが、カンマ区切りの値が得られている。

 リストを要素とするリストをテキストファイルに書き込む場合についても考えてみよう。以下はファイルオブジェクトのwriteメソッドやwritelinesメソッドを使って、これを行う例だ(詳しい解説は省略)。

l0 = [[1, 2, 3], [4, 5, 6]]

result = ''
with open(filename, 'w') as f:
    for l in l0:
        result += ', '.join([str(x) for x in l]) + '\n'
    f.write(result)

with open(filename, 'w') as f:
    for l in l0:
        result = ', '.join([str(x) for x in l]) + '\n'
        f.write(result)

with open(filename, 'w') as f:
    result = []
    for l in l0:
        result.append(', '.join([str(x) for x in l]) + '\n')
    #result = [', '.join([str(x) for x in l]) + '\n' for l in l0]
    f.writelines(result)

with open(filename) as f:
    contents = f.read()
    print(contents)  # 省略


 いずれの例でも、リストの各行について先ほどと同様に、文字列のjoinメソッドとstr関数を組み合わせて文字列化し、できた結果をwriteメソッドまたはwritelinesメソッドでテキストファイルに書き込んでいる。やりたいことはシンプルだが、それなりのコード量になっている(writelinesメソッドの例でコメントアウトしてあるコードではリスト内包表記を使っているが、これを読み下すのはちょっと面倒だと感じる人もいるだろう)。

 これに対して、print関数を使った場合は次のようになる。

l0 = [[1, 2, 3], [4, 5, 6]]

with open(filename, 'w') as f:
    for l in l0:
        print(*l, sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)


 各行について、その行の要素を展開してprint関数に渡すだけで済むので、コードがシンプルになっている。print関数をうまく使えば、こうしたことも可能なことは覚えておこう。

 ただし、CSV形式のファイルで文字列として処理したい部分はシングルクオートで囲みたいといったときには一手間がかかることにも注意したい。以下に例を示す。

l0 = [['1', '2', '3'], [4, 5, 6]]
with open(filename, 'w') as f:
    for l in l0:
        print(*l, sep=', ', file=f)
        print(*[repr(x) for x in l], sep=', ', file=f)

with open(filename) as f:
    contents = f.read()
    print(contents)
# 出力結果:
#1, 2, 3
#'1', '2', '3'
#4, 5, 6
#4, 5, 6


 この例では文字列リストと整数リストを要素とするリストを使用している。このときに、単純にそれらの要素をprint関数に渡すだけだと、文字列も整数も同じように出力されてしまう。このときにはrepr関数を使うなどして、オブジェクトの公式な表現(印字可能な表現)にすることで文字列は文字列として、整数は整数として出力できる(オブジェクトの種類によっては無理なことがある)。

 比較用に上の例では、文字列リストと整数リストのそれぞれをそのままprint関数に渡すコードと、それらをrepr関数で変換したものをprint関数に渡すコードを記述してある。

 出力結果の最初の2行は文字列リストのものだが、これを見ると、そのまま渡した場合は「1, 2, 3」とこれが文字列か整数かが分からなくなってしまっているが、repr関数を介した場合には「'1', '2', '3'」のように文字列として出力されていることが確認できる。一方、整数リストについてはどちらの場合も「1, 2, 3」と出力されている。よって、このことを使えば、CSVファイルでの整数と文字列の区別なども行えるようになるだろう。

 print関数を使って、テキストファイルに出力するとコードがスッキリできることもあるが、注意すべき点もあるので、うまい使い方を考えてみてほしい。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。