[Programming Language]/[Python]

[Python] :: 파일 처리(파일 입출력) - open(), close(), read(), write(), with 키워드

Semincolon 2023. 7. 6. 11:29

◎ 파일 처리(파일 입출력)

  파이썬에는 파일과 관련된 처리를 하는 표준 함수들이 기본적으로 제공된다. 제공되는 함수는 아래 표를 통해 나타내었다. 아래 표의 내용을 하나

open( ) 파일 열기
close( ) 파일 닫기
read( ) 파일 내용 읽기
readline( ) 파일 내용 한 줄씩 읽기
readlines( ) 파일 내용 전체를 한 줄씩 읽어 리스트 형태로 읽기
wrtie( ) 파일에 내용 쓰기
writelines( ) 리스트 내용을 파일에 쓰기
seek( ) 파일의 커서를 해당 위치로 옮기기
tell( ) 현재 커서의 위치 가져오기
with 키워드 파일 자동으로 닫기

 

1) open( )

  파일을 다루기 위해선 먼저 파일을 여는 과정이 필요한데 이때 사용되는 함수가 open()이다. 기본 형태는 다음과 같다.

파일 변수 = open(파일 경로, 읽기 모드)

  파일 경로는 현재 파일의 위치를 기준으로 작성하면 된다. 만약 현재 파일의 위치와 같은 위치에 존재하는 파일을 열 것이라면 "./test.txt" 또는 "test.txt"라고 작성하면 된다.

  읽기 모드는 파일을 가져와 어떤 일을 할 것인지에 따라 결정하면 된다. 읽기 모드는 아래 표와 같다.

r (기본값)읽기 모드
w 쓰기 모드
a 쓰기 모드(이어쓰기)
x 쓰기 모드(파일이 없으면 생성, 있으면 오류)

  r 모드는 파일 내용을 읽을 때 사용하는 모드이고, w, a, x 모드는 파일에 내용을 쓸 때 사용하는 모드이다. w 모드는 파일의 원래 내용을 덮어쓰고 a 모드는 파일의 기존 내용의 맨 뒤에부터 새로운 내용을 작성하고 x 모드는 파일이 있는 경우에는 오류가 나고 없는 경우에만 파일이 생성되어 쓰기가 가능하다.

 

2) close( )

  만약 파일을 열었다면 이를 다시 닫는 과정이 꼭 필요하다. 파일을 닫지 않아도 프로그램이 종료될 때 자동으로 파일이 닫히지만 그래도 닫는 습관을 들이는 것이 좋다. 기본 형태는 다음과 같다.

파일 변수.close()

    파일이 올바르게 닫혔는지를 확인하기 위해선 closed를 사용하면 된다. 아래 코드는 파일을 열었을 때의 상태와 닫고 나서의 상태를 확인하고 있다.

file = open("test.txt", "r")
print("현재 파일 상태:", file.closed)

file.close()
print("현재 파일 상태:", file.closed)

2-1) with 키워드

  with 키워드는 파일을 자동으로 닫아주는 기능을 한다. 이것을 사용하면 까먹고 파일을 닫지 않는 경우를 예방할 수 있다.

with open("test.txt", "r") as file:
    print("파일을 열었습니다.")
    print("현재 파일 상태:", file.closed)
    print()

print("with 구문 실행 종료")
print("현재 파일 상태:", file.closed)

3) read( ), readline( ), readlines( )

  read( ), readline( ), readlines( ) 함수는 파일의 내용을 읽을 때 사용하는 함수이다. 파일의 내용을 읽는 것이므로 읽기 모드는 r이 된다. 현재 파일과 같은 위치에 존재하는 아래의 test.txt 파일의 내용을 읽어와보자.

 

3-1) read( )

  read( ) 함수는 괄호 안의 숫자(인자) 만큼의 문자를 읽어오는 함수이다. 파일의 내용보다 인자가 더 크더라도 상관은 없다. 만약 인자가 전달되지 않다면 파일의 모든 내용을 읽어오게 된다.

file = open("test.txt", "r")

print("case 1)")
text = file.read(3)
print(text)
print()

print("case 2)")
text = file.read(9999)
print(text)
print()

print("case 3)")
text = file.read()
print(text)

file.close()

**중요 !! 
  그런데 예상했던 결과와 실제 출력 결과가 차이가 나는 모습을 볼 수 있다. 이유는 바로 '커서'라는 개념 때문이다. 파일 내용에 접근할 때 어디까지 접근했는지에 대한 커서가 위치하게 되는데 case 1에서 총 3개의 문자를 출력했으므로 현재 커서의 위치는 Hel 문자 바로 뒤이다. 이후 case 2에서 9999(나머지 모두)개의 문자를 출력했으므로 파일의 모든 문자가 출력되었고 case 3에서의 커서의 위치는 이미 파일의 마지막이므로 아무 것도 출력되지 않는 것이다.

 

3-2) readline( )

  readline( )은 파일의 내용을 읽되 한 줄씩, 즉 '\n(개행 문자)'를 만날 때까지 내용을 읽어오는 함수이다.

file = open("test.txt", "r")

text = file.readline()
print(text)

text = file.readline()
print(text)

text = file.readline()
print(text)

text = file.readline()
print(text)

text = file.readline()
print(text)

file.close()

3-3) readlines( )

  readlines( ) 함수는 파일의 내용 전체를 줄 단위로 읽어 이를 리스트 형태로 읽어오는 함수이다.

file = open("test.txt", "r")

text = file.readlines()
print(text)

file.close()

4) write( ), writelines( )

  이 두 함수는 파일에 새로운 내용을 작성할 때 사용하는 함수이다. 읽기와는 달리 쓰는 것이므로 읽기 모드는 w가 된다. 마찬가지로 현재 파일과 동일한 위치에 있는 "test.txt" 파일에 새로운 내용을 작성해보자.

file = open("test.txt", "w")
file.write("새로운 내용 입력 \n")
file.writelines('\n'.join(["Hello", "Nice", "to", "meet", "you!"]))
file.close()

  위에서 보았던 내용이 삭제되고 새로운 내용으로 바뀐 것을 확인할 수 있다. 여기서 포인트는 줄 단위로 입력을 하기 위해서는 '\n(개행 문자)'도 반드시 입력해야 한다는 것이다. 그렇다면 이번에는 읽기 모드를 a로 하면 어떻게 될까?

file = open("test.txt", "a")
file.write("\n")
file.write("새로운 내용 입력 \n")
file.writelines('\n'.join(["Hello", "Nice", "to", "meet", "you!"]))
file.close()

  읽기 모드를 a로 변경하니 기존의 내용이 삭제되지 않고 마지막 부터 새로운 내용이 추가로 작성되었다. 그럼 읽기 모드 x는 어떨까?

file = open("test.txt", "x")
file.write("\n")
file.write("새로운 내용 입력 \n")
file.writelines('\n'.join(["Hello", "Nice", "to", "meet", "you!"]))
file.close()

  읽기 모드를 x로 변경하니 현재 이미 test.txt 파일이 존재하기 때문에 FileExistsError가 발생하게 된다.

 

5) seek( ), tell( )

  seek( ) 함수는 현재 파일에 위치한 커서의 위치를 이동하는 함수이고, tell( ) 함수는 현재 커서의 위치를 반환하는 함수이다. 각 함수의 기본 형태는 다음과 같다.

# seek( ) 함수 기본 형태
파일 변수.seek(offset, whence(기준위치, 기본값 = 0))

# tell( ) 함수 기본 형태
파일 변수.tell()

  seek( ) 함수의 offset이란 이동할 바이트를 뜻한다. 양수일 경우 뒤쪽으로 이동하는 것을 뜻하고 음수일 경우 앞쪽으로 이동하는 것을 뜻한다. 기준위치는 파일의 맨 앞을 뜻하는 0, 현재 커서의 위치를 뜻하는 1, 파일의 맨 뒤를 뜻하는 2가 있다. 그러나 텍스트 파일에서는 기준위치 0만 사용 가능하다. 아래 예제를 통해 확인해보자.

file = open("test.txt", "r")

print("<case 1>")
print(file.readline())
print()

print("<case 2>")
print(file.readline())

print("<case 3>")
file.seek(0)
print(file.tell())
print(file.readline())
print()

print("<case 4>")
file.seek(4, 0)
print(file.tell())
print(file.readline())
print()

print("<case 5>")
file.seek(3, 0)
print(file.tell())
print(file.readline())
print()

file.close()

  앞서 계속 다루었던 "test.txt" 파일의 내용을 읽어 보았다. case 1과 2에서는 한 줄씩 커서가 이동하며 파일의 내용을 읽고 있다. case 3에서는 커서의 위치를 파일의 맨 앞으로 이동시킴에 따라 다시 파일의 맨 앞에서부터 출력이 이뤄지고 있다. case 4에서는 커서의 위치를 파일의 맨 앞을 기준으로 4바이트(영어 4글자, 한글 2글자)만큼 뒤로 이동하였기 때문에 "새로" 뒤의 "운 내용 입력" 부분만 출력이 이뤄지고 있다. case 5는 3바이트만큼 뒤로 이동하였는데 한글은 한 글자에 2바이트이기 때문에 홀수 단위로는 이동이 불가능하다는 오류가 출력되고 있다.