ValueError: Python에서 닫힌 파일에 대한 I/O 작업 해결

Jay Shaw 2023년10월8일
  1. Python에서 부적절한 들여쓰기로 인한 ValueError: I/O operation on closed file 해결
  2. Python의 for 루프 내부 파일 닫기로 인한 ValueError: I/O operation on closed file 해결
  3. 닫힌 파일에서 쓰기 작업 수행으로 인한 ValueError: I/O operation on closed file 해결
  4. 결론
ValueError: Python에서 닫힌 파일에 대한 I/O 작업 해결

리소스 관리는 프로그래밍에서 중요한 요소입니다. 그러나 종종 프로그래머는 자신도 모르게 메모리 블록을 열어 두어 메모리 오버플로를 유발할 수 있습니다.

그러나 이 기사에서는 Python의 오류인 ValueError: I/O operation on closed file을 살펴봅니다. 이것은 프로그래머가 작업 사이에 닫히는 파일에 대해 작업을 수행하려고 할 때 발생합니다.

ValueError: I/O operation on closed file이 발생할 수 있는 주로 세 가지 경우가 있습니다.

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를 가져옵니다. 코드의 두 번째 줄에서는 with 문을 사용하여 예외 처리 블록을 생성하고, 키워드 r을 사용하여 .csv 파일인 sample_submission.csvemployees 객체 내에 읽을 수 있는 엔티티로 저장합니다.

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

ValueError: I/O operation on closed filewith 예외 처리 문으로 인해 발생했습니다. 앞에서 말했듯이 with 문은 예외 처리 블록을 만들고 내부에서 시작된 모든 작업은 컴파일러가 이 블록을 벗어나는 즉시 종료됩니다.

위의 프로그램에서 들여쓰기 실수로 오류가 발생했습니다. Python 컴파일러는 줄의 끝을 식별하기 위해 세미콜론을 사용하지 않습니다. 대신 공간을 사용합니다.

코드에서 for 루프는 with 블록 외부에서 생성되어 파일을 닫습니다. for 루프가 with 바로 아래에 작성되었지만 부적절한 들여쓰기로 인해 컴파일러는 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(value of c).txt라는 이름으로 새 파일에 씁니다.

변수 bsample.txt 파일과 함께 로드되는 반면 변수 f는 새 파일에 쓰는 데 사용됩니다. for 루프는 b 내부에 로드된 파일 내의 라인 수에 대해 실행됩니다.

반복할 때마다 a가 증가하고 a=5인 반복에서 a 값은 0으로 재설정됩니다.

프로세스가 완료되면 f.close()가 두 번 사용됩니다. 첫 번째 f.closef를 지우고 두 번째 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