ValueError を解決する: Python で閉じたファイルに対する I/O 操作
-
Python の不適切なインデントによる
ValueError: I/O operation on closed file
を解決する -
Python の
for
ループ内でファイルを閉じることによるValueError: I/O operation on closed file
を解決する -
閉じたファイルに書き込み操作を実行することによる
ValueError: I/O operation on closed file
を解決する - まとめ
リソース管理は、プログラミングにおいて重要な要素です。 しかし、多くの場合、プログラマーはメモリ ブロックを開いたままにしておくと、メモリ オーバーフローが発生する可能性があります。
ただし、この記事では、Python のエラーに注目しています: ValueError: I/O operation on closed file
. これは、プログラマーがファイルに対して操作を実行しようとしたときに発生し、操作の合間に閉じられます。
ValueError: I/O operation on closed file
が発生する可能性がある主なケースは 3つあります。
Python の不適切なインデントによる ValueError: I/O operation on closed file
を解決する
プログラマーが、Python コンパイラーを使用してメモリにロードしようとする .csv
ファイルを持っているとします。 Python では、ファイルの内容を読み込んでファイルを読み書きするには、オブジェクト変数を作成する必要があります。
以下のプログラムでこれを理解しましょう。
import csv
# Open the file in Read mode
with open("sample_submission.csv", "r") as employees:
read_csv = csv.reader(employees)
このプログラムは、.csv
ファイルを読み込むためにライブラリパッケージ csv
をインポートします。コードの2行目では、プログラムは例外処理ブロックを作成し、キーワード r
を使用して .csv
ファイル sample_submission.csv
をオブジェクト employees
に読み取り可能なエンティティとして格納します。
エンティティemployees
を読み取るために、いくらかのメモリを割り当てる必要があります。 コードの 3 行目では、メモリ ブロックを read_csv
に割り当てて、 employees
の内容を保存します。
プログラマーが .csv
ファイルから行を表示したい場合、以下のコードのように、for
ループ内でオブジェクト read_csv
から行を出力する必要があります。
import csv
# Open the file in Read mode
with open("sample_submission.csv", "r") as employees:
read_csv = csv.reader(employees)
# iterate and print the rows of csv
for row in read_csv:
print("Rows: ", row)
しかし、プログラマーがこのコードをコンパイルしようとすると、エラーが発生します。
"C:\Users\Win 10\main.py"
Traceback (most recent call last):
File "C:\Users\Win 10\main.py", line 8, in <module>
for row in read_csv:
ValueError: I/O operation on closed file.
Process finished with exit code 1
with
例外処理ステートメントが原因で ValueError: I/O operation on closed file
が発生しました。 前に述べたように、with
ステートメントは例外処理ブロックを作成し、内部で開始されたすべての操作は、コンパイラがこのブロックから出るとすぐに終了します。
上記のプログラムでは、インデントの誤りが原因でエラーが発生しました。 Python コンパイラは、セミコロンを使用して行末を識別しません。 代わりに、スペースを使用します。
コードでは、for
ループが with
ブロックの外側に作成されているため、ファイルが閉じられています。 with
のすぐ下に for
ループが記述されていたにもかかわらず、不適切なインデントにより、コンパイラは for
ループが with
ブロックの外側にあると判断しました。
この問題の解決策は、次のように適切なインデントを特定することです。
import csv
with open("sample_submission.csv", "r") as employees:
read_csv = csv.reader(employees)
# for loop is now inside the with block
for row in read_csv:
print("Rows: ", row)
出力:
"C:\Users\Win 10\main.py"
Rows: ['Employee ID', 'Burn Rate']
Rows: ['fffe32003000360033003200', '0.16']
Rows: ['fffe3700360033003500', '0.36']
Rows: ['fffe31003300320037003900', '0.49']
Rows: ['fffe32003400380032003900', '0.2']
Rows: ['fffe31003900340031003600', '0.52']
Process finished with exit code 0
Python の for
ループ内でファイルを閉じることによる ValueError: I/O operation on closed file
を解決する
この例は、with
ステートメントを使用せずに ValueError: I/O operation on closed file
がどのように発生するかを示しています。 Python スクリプトがファイルを開き、ループ内で何かを書き込む場合、プログラムの最後でファイルを閉じる必要があります。
ただし、ループ内で明示的にファイルを閉じると、ValueError: I/O operation on closed file
が発生する可能性があります。 上で説明したように、with
ブロックはその内部で開始されたものをすべて閉じます。
ただし、for
ループなどが使用されている場合、ループの途中でファイルが閉じられると ValueError: I/O operation on closed file
が発生します。 以下のプログラムでこれがどのように行われるかを見てみましょう。
a = 0
b = open("sample.txt", "r")
c = 5
f = open("out" + str(c) + ".txt", "w")
for line in b:
a += 1
f.writelines(line)
if a == c:
a = 0
f.close()
f.close()
上記のコードは、ファイル sample.txt
から内容を読み取り、それらの内容を out(c の値).txt
という名前の新しいファイルに書き込みます。
変数 b
は sample.txt
ファイルと共にロードされ、変数 f
は新しいファイルへの書き込みに使用されます。 b
内にロードされたファイル内の行数に対して、for
ループが実行されます。
各反復は a
を増加させますが、a=5
の反復で a
の値はゼロにリセットされます。
処理が完了すると、f.close()
が 2 回使用されます。 最初の f.close
は f
をクリアし、2 番目は b
をクリアします。
しかし、ファイルが閉じられる前に、プログラムはさらに反復を実行する必要がありました。 プログラムがコンパイルされると、次の出力が得られます。
"C:\Users\Win 10\main.py"
Traceback (most recent call last):
File "C:\Users\Win 10\main.py", line 8, in <module>
f.writelines(line)
ValueError: I/O operation on closed file.
Process finished with exit code 1
これは、ファイルが for
ループ内で閉じられているために発生します。これにより、以降の反復でファイルを読み取ることができなくなります。
このエラーは偶発的に発生するため、解決するにはコードに戻ってファイルが閉じられる場所を再確認する必要があります。 for
ループの場合、ループのインデントの外側でファイルを閉じる必要があります。これにより、ループがすべての反復を完了し、メモリを解放できます。
a = 0
b = open("sample.txt", "r")
c = 5
f = open("out" + str(c) + ".txt", "w")
for line in b:
a += 1
f.writelines(line)
if a == c:
a = 0
f.close()
ここでは、ファイルは for
ループのインデントの外側で閉じられているため、コンパイラはすべての反復が完了した後にファイルを閉じます。
コードがコンパイルされると、out5.txt
という名前のファイルの作成中にエラーはスローされません。
"C:\Users\Win 10\main.py"
Process finished with exit code 0
閉じたファイルに書き込み操作を実行することによる ValueError: I/O operation on closed file
を解決する
これは、プログラマーが以前に閉じられたファイルに書面による指示を与え、それをコンパイルすると ValueError: I/O operation on closed file
エラーが生成されるケース シナリオです。
例を見てみましょう:
with open("gh.txt", "w") as b:
b.write("Apple\n")
b.write("Orange \n")
b.write("Guava \n")
b.close()
b.write("grapes")
プログラムは .txt
ファイルをオブジェクト b
として読み込みます。 次に、このオブジェクト変数 b
を使用して、.txt
ファイル内で書き込み操作を実行します。
このコードをコンパイルすると、ValueError: I/O operation on closed file
が発生します。
"C:\Users\Win 10\main.py"
Traceback (most recent call last):
File "C:\Users\Win 10\main.py", line 6, in <module>
b.write("grapes")
ValueError: I/O operation on closed file.
Process finished with exit code 1
これは、書かれたステートメントの上に書かれた b.close()
ステートメントが原因でした。 コンパイラは、with
ブロック内であっても、ファイルの書き込みを許可しません。
この問題を解決するには、b.close
を追加する必要がある場合は、プログラムを with
ステートメントなしで書き直す必要があります。
b = open("gh.txt", "w")
b.write("Apple\n")
b.write("Orange \n")
b.write("Guava \n")
b.write("grapes")
b.close()
または、b.close()
ステートメントを with
ステートメントから削除して実行する必要があります。
with open("gh.txt", "w") as b:
b.write("Apple\n")
b.write("Orange \n")
b.write("Guava \n")
b.write("grapes")
どちらのコード ブロックも同じ作業を実行しますが、with
ステートメントを使用すると、例外処理が追加され、コードがクリアされます。
まとめ
この記事では、ValueError: I/O operation on closed file
が発生するさまざまな理由について説明しました。 読者は、with
ステートメントを理解し、将来的に正しく使用する必要があります。
関連記事 - Python Error
- AttributeError の解決: 'list' オブジェクト属性 'append' は読み取り専用です
- AttributeError の解決: Python で 'Nonetype' オブジェクトに属性 'Group' がありません
- AttributeError: 'generator' オブジェクトに Python の 'next' 属性がありません
- AttributeError: 'numpy.ndarray' オブジェクトに Python の 'Append' 属性がありません
- AttributeError: Int オブジェクトに属性がありません
- AttributeError: Python で 'Dict' オブジェクトに属性 'Append' がありません