파이썬 기초 강좌: 7. 파일 예제와 실습 (Python Basics – File Examples and Exercises)

파이썬 기초 강좌에 오신 것을 환영합니다. 이 장에서는 보조 메모리, 즉 파일을 다루는 방법에 대해 배웁니다. 보조 메모리는 전원이 꺼져도 데이터가 지워지지 않는 저장 장치입니다. 우리는 주로 텍스트 편집기에서 생성하는 텍스트 파일을 읽고 쓰는 것에 초점을 맞출 것입니다. 파일을 효과적으로 관리하고 활용하는 방법을 익히면서, 데이터를 안전하게 저장하고 불러오는 기술을 배워보세요.

파이썬 기초 강좌 - 파일 예제와 실습

1. 파이썬 기초 강좌 – Opening files

  • 파일에 쓰거나 읽기 위해서는 파일을 open 해야 합니다.
  • 사용이 끝나면 파일을 close 해야 합니다.
  • 파일 다운로드: www.py4e.com/code3/mbox.txt
  • 다운로드 받은 파일은 파이썬 스크립트와 같은 디렉토리에 저장하세요.
  • (실습) 대화식 모드에서 실행해 보세요.
>>> fhand = open("mbox.txt")
>>> print(fhand)
<_io.TextIOWrapper name='mbox.txt' mode='r' encoding='cp949'>
>>> fhand.close()

>>> fhand = open("stuff.txt")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'stuff.txt'
>>> 

2. Text files and lines

  • 텍스트 파일은 문자열의 연속처럼 생각할 수 있으며,
  • 파이썬 문자열도 문자의 연속으로 생각할 수 있습니다.
  • 다음은 텍스트 파일의 예시입니다: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 Return-Path: postmaster@collab.sakaiproject.org Date: Sat, 5 Jan 2008 09:12:18 -0500 To: source@collab.sakaiproject.org From: [stephen.marquard@uct.ac.za] Subject: [sakai] svn commit: r39772 – content/branches/ Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772
  • 파일을 여러 줄로 나누기 위해, “줄의 끝”을 나타내는 특별한 문자가 있는데,
  • 이를 줄바꿈 문자라고 합니다. (newline)
  • 파이썬에서는 문자열 상수에서 줄바꿈 문자를 backslash-n으로 표현합니다.
  • (실습)
>>> stuff = 'Hello\nWorld!'
>>> stuff
'Hello \nWorld!'
>>> print(stuff)
Hello
World!
>>> stuff = 'X\nY'
>>> print(stuff)
X
Y
>>> len(stuff)
3
>>> s1 = "stuff\n"
>>> s1
'stuff\n'
>>> print(s1)
stuff

>>> s1.strip()
'stuff'
>>> print(s1.strip())
stuff
>>>

3. Reading files

  • 다운로드: www.py4e.com/code3/mbox-short.txt
  • 다운받은 파일을 파이썬 스크립트와 같은 위치에 저장하세요.
  • 파일 핸들을 for 루프에서 시퀀스로 사용할 수 있습니다.
  • 아래 코드의 for 루프는 단순히 파일의 줄 수를 세고 그것들을 출력합니다.
  • for 루프를 대략 번역하면, “파일 핸들로 표현된 파일의 각 줄에 대해, 카운트 변수에 하나를 더하라” 입니다.
  • (실습)
# open.py

fhand = open('mbox-short.txt')

count = 0
for line in fhand:
    print(line)
    count += 1

fhand.close()

print('Line Count:', count)
  • open 함수가 파일 전체를 읽지 않는 이유는 파일이 매우 클 수 있고 수기가바이트의 데이터를 포함할 수 있기 때문입니다.
  • open 문은 파일의 크기와 상관없이 동일한 시간이 걸립니다.
  • for 루프가 실제로 파일에서 데이터를 읽게 합니다.
  • 이런 방식으로 for 루프를 사용하여 파일을 읽을 때, 파이썬은 파일 내의 데이터를 줄바꿈 문자를 사용하여 별도의 줄로 나누는 것을 처리합니다.
  • 파이썬은 각 줄을 줄바꿈을 통해 읽고, for 루프의 각 반복에서 줄 변수의 마지막 문자로 줄바꿈을 포함합니다.
  • for 루프가 한 번에 한 줄씩 데이터를 읽기 때문에, 주 메모리에 데이터를 저장할 공간이 부족해지지 않고 매우 큰 파일의 줄을 효율적으로 읽고 세울 수 있습니다.
  • 위 프로그램은 매우 적은 메모리를 사용하여 어떤 크기의 파일이든 줄 수를 셀 수 있습니다.
  • 각 줄은 읽히고, 세어지며, 그 다음 버려집니다.
  • 만약 파일이 주 메모리의 크기에 비해 상대적으로 작다는 것을 알고 있다면, 파일 핸들의 read 메소드를 사용하여 전체 파일을 하나의 문자열로 읽을 수 있습니다.
  • (실습#1)
>>> f = open("mbox-short.txt")
>>> inp = f.read()
>>> print(len(inp))
94626
>>> print(inp[:20])
From stephen.marquar
>>> type(inp)
<class 'str'>
>>> f.close()
  • open("mbox-short.txt"): “mbox-short.txt” 파일을 엽니다.
  • f.read(): 파일 전체 내용을 하나의 문자열로 읽습니다.
  • print(len(inp)): 문자열의 길이(문자 수)를 출력합니다. 결과는 94626입니다.
  • print(inp[:20]): 처음 20문자를 출력합니다.
  • type(inp): inp의 타입을 확인합니다. 문자열(<class 'str'>)입니다.
  • f.close(): 파일을 닫습니다.
>>> f = open("mbox-short.txt")
>>> inp2 = f.readlines()
>>> type(inp2)
<class 'list'>
>>> f.close()
  • f.readlines(): 파일의 각 줄을 요소로 하는 리스트를 반환합니다.
  • type(inp2): inp2의 타입을 확인합니다. 리스트(<class 'list'>)입니다.
  • f.close(): 파일을 닫습니다.
>>> f = open("mbox-short.txt")
>>> line = f.readline()
>>> line
'From stephen.marquard@uct.ac.za Sat Jan  5 09:14:16 2008\\n'
>>> line = f.readline()
>>> line
'Return-Path: <postmaster@collab.sakaiproject.org>\\n'
>>> 
  • f.readline(): 파일에서 한 줄을 읽어옵니다.
  • 첫 번째 readline() 호출: 첫 번째 줄을 읽어와서 line에 저장합니다.
  • 두 번째 readline() 호출: 두 번째 줄을 읽어와서 line에 저장합니다.
  • (실습#2)
>>> fhand = open('mbox-short.txt')
>>> print(len(fhand.read()))
94626
>>> print(len(fhand.read()))
0
>>> fhand.close()
>>>
  • fhand = open('mbox-short.txt'): “mbox-short.txt” 파일을 엽니다.
  • fhand.read(): 파일의 전체 내용을 읽고, 파일 포인터를 파일의 끝으로 이동시킵니다. fhand.read()는 파일의 내용을 하나의 문자열로 반환합니다.
  • print(len(fhand.read())): 첫 번째 read() 호출 결과의 길이를 출력합니다. 결과는 94626입니다. 이 호출 후 파일 포인터는 파일의 끝에 위치하게 됩니다.
  • print(len(fhand.read())): 두 번째 read() 호출 시, 파일 포인터가 이미 파일의 끝에 있으므로 빈 문자열을 반환합니다. 결과는 0입니다.
  • fhand.close(): 파일을 닫습니다.

4. Searching through a file

  • (실습#1)
# search1.py

fhand = open('mbox-short.txt')

for line in fhand:
        if line.startswith('From:'):
        print(line)

fhand.close()

# output:
# From: stephen.marquard@uct.ac.za
#
# From: louis@media.berkeley.edu
#
# From: zqian@umich.edu
#
# From: rjlowe@iupui.edu

이 실습에서는 파일에서 특정 패턴을 찾아 출력하는 방법을 배울 수 있습니다.

  1. fhand = open('mbox-short.txt'): “mbox-short.txt” 파일을 엽니다.
  2. for line in fhand:: 파일의 각 줄을 순회합니다.
  3. if line.startswith('From:'):: 각 줄이 ‘From:’으로 시작하는지 확인합니다.
  4. print(line): ‘From:’으로 시작하는 줄을 출력합니다.
  5. fhand.close(): 파일을 닫습니다.
  • (실습#2)
# search2.py
fhand = open("mbox-short.txt")

for line in fhand:
        line = line.rstrip()
        if line.startswith("From:"):
                print(line)

fhand.close()

이 실습에서는 파일에서 특정 패턴을 찾아 출력하는 동안 줄 끝의 불필요한 공백을 제거하는 방법을 배웁니다.

  1. fhand = open("mbox-short.txt"): “mbox-short.txt” 파일을 엽니다.
  2. for line in fhand:: 파일의 각 줄을 순회합니다.
  3. line = line.rstrip(): 현재 줄에서 오른쪽 끝에 있는 모든 공백 문자를 제거합니다.
  4. if line.startswith("From:"):: 각 줄이 ‘From:’으로 시작하는지 확인합니다.
  5. print(line): ‘From:’으로 시작하는 줄을 출력합니다.
  6. fhand.close(): 파일을 닫습니다.
  • (실습#3)
# search3.py
fhand = open('mbox-short.txt')

for line in fhand:
        line = line.rstrip()
        # Skip 'uninteresting lines'
        if not line.startswith('From:'):
                continue
        # Process our 'interesting' line
        print(line)

fhand.close()

이 실습에서는 파일에서 특정 패턴을 포함하지 않는 줄을 건너뛰고, 필요한 줄만 처리하는 방법을 배웁니다.

  1. fhand = open('mbox-short.txt'): “mbox-short.txt” 파일을 엽니다.
  2. for line in fhand:: 파일의 각 줄을 순회합니다.
  3. line = line.rstrip(): 현재 줄에서 오른쪽 끝에 있는 모든 공백 문자를 제거합니다.
  4. if not line.startswith('From:'):: 각 줄이 ‘From:’으로 시작하지 않으면 그 줄을 건너뜁니다.
  5. continue: ‘From:’으로 시작하지 않는 줄은 건너뜁니다.
  6. print(line): ‘From:’으로 시작하는 줄만 출력합니다.
  7. fhand.close(): 파일을 닫습니다.
  • (실습#4)
# search4.py
fhand = open('mbox-short.txt')

for line in fhand:
        line = line.rstrip()
        if line.find('@uct.ac.za') == -1:
                continue
        print(line)

fhand.close()

이 실습에서는 파일에서 특정 문자열을 포함하는 줄만 출력하는 방법을 배웁니다.

  1. fhand = open('mbox-short.txt'): “mbox-short.txt” 파일을 엽니다.
  2. for line in fhand:: 파일의 각 줄을 순회합니다.
  3. line = line.rstrip(): 현재 줄에서 오른쪽 끝에 있는 모든 공백 문자를 제거합니다.
  4. if line.find('@uct.ac.za') == -1:: 현재 줄에 ‘@uct.ac.za’가 포함되지 않으면 그 줄을 건너뜁니다.
  5. continue: ‘@uct.ac.za’를 포함하지 않는 줄은 건너뜁니다.
  6. print(line): ‘@uct.ac.za’를 포함하는 줄만 출력합니다.
  7. fhand.close(): 파일을 닫습니다.

5. Letting the user choose the file name

  • 사용자가 파일 이름을 선택하도록 하기
  • (실습)
# search5.py
fname = input('Enter the file name: ')
fhand = open(fname)

count = 0
for line in fhand:
        if line.startswith('Subject:'):
                count = count + 1
fhand.close()

print('There were', count, 'subject lines in', fname)

이 실습에서는 사용자가 파일 이름을 입력하도록 하여, 해당 파일에서 특정 패턴을 찾고 그 빈도를 세는 프로그램을 작성합니다.

  1. fname = input('Enter the file name: '): 사용자에게 파일 이름을 입력받습니다.
  2. fhand = open(fname): 입력된 파일 이름을 사용하여 파일을 엽니다.
  3. count = 0: ‘Subject:’로 시작하는 줄의 개수를 세기 위해 count 변수를 0으로 초기화합니다.
  4. for line in fhand:: 파일의 각 줄을 순회합니다.
  5. if line.startswith('Subject:'):: 각 줄이 ‘Subject:’로 시작하는지 확인합니다.
  6. count = count + 1: ‘Subject:’로 시작하는 줄을 찾으면 count를 1씩 증가시킵니다.
  7. fhand.close(): 파일을 닫습니다.
  8. print('There were', count, 'subject lines in', fname): ‘Subject:’로 시작하는 줄의 총 개수를 출력합니다.

6. Using try, except, and open

  • (실습)
# search6.py
fname = input('Enter the file name: ')
try:
        fhand = open(fname)
except:
        print('File cannot be opened:', fname)
        exit()

count = 0
for line in fhand:
        if line.startswith('Subject:'):
        count = count + 1
fhand.close()

print('There were', count, 'subject lines in', fname)

이 실습에서는 파일을 열 때 발생할 수 있는 오류를 처리하기 위해 tryexcept를 사용하는 방법을 배웁니다.

  1. fname = input('Enter the file name: '): 사용자에게 파일 이름을 입력받습니다.
  2. try: fhand = open(fname): 파일을 열려고 시도합니다.
  3. except: print('File cannot be opened:', fname) exit(): 파일을 열 수 없는 경우, 오류 메시지를 출력하고 프로그램을 종료합니다.
  4. count = 0: ‘Subject:’로 시작하는 줄의 개수를 세기 위해 count 변수를 0으로 초기화합니다.
  5. for line in fhand:: 파일의 각 줄을 순회합니다.
  6. if line.startswith('Subject:'):: 각 줄이 ‘Subject:’로 시작하는지 확인합니다.
  7. count = count + 1: ‘Subject:’로 시작하는 줄을 찾으면 count를 1씩 증가시킵니다.
  8. fhand.close(): 파일을 닫습니다.
  9. print('There were', count, 'subject lines in', fname): ‘Subject:’로 시작하는 줄의 총 개수를 출력합니다.

7. Writing files

  • (실습#1)
>>> fout = open("output.txt", "w", encoding="utf-8")
>>> print(fout)
<_io.TextIOWrapper name='output.txt' mode='w' encoding='cp949'>
>>> line1 = "This here's the wattle,\n"
>>> fout.write(line1)
24
>>> fout.close()
>>> 

이 실습에서는 파일에 데이터를 쓰는 방법을 배웁니다.

  1. fout = open("output.txt", "w", encoding="utf-8"): “output.txt”라는 이름의 파일을 쓰기 모드("w")로 열고, UTF-8 인코딩을 사용합니다. 파일 객체는 fout에 저장됩니다.
  2. print(fout): 파일 객체 fout의 정보를 출력합니다. 파일 이름, 모드, 인코딩 정보를 확인할 수 있습니다.
  3. line1 = "This here's the wattle,\n": 파일에 쓸 문자열을 정의합니다. 문자열 끝에 있는 \n은 줄바꿈 문자를 나타냅니다.
  4. fout.write(line1): 문자열 line1을 파일에 씁니다. 반환값은 쓰여진 문자 수입니다. 이 경우, 24자를 파일에 씁니다.
  5. fout.close(): 파일을 닫아줍니다. 파일을 닫는 것은 매우 중요하며, 이는 모든 데이터가 파일에 올바르게 기록되도록 보장합니다.
  • (실습#2)
>>> with open('output3.txt', 'w') as f:
...     line1 = "aaa"
...     line2 = "bbb"
...     f.write("aaa")
...     f.write(line2)
...
3
3
>>> with open('output3.txt') as f:
...     for line in f:
...         print(line)
...
aaabbb
>>>

이 실습에서는 with 문을 사용하여 파일에 데이터를 쓰고 읽는 방법을 배웁니다.

  1. with open('output3.txt', 'w') as f:: “output3.txt”라는 이름의 파일을 쓰기 모드("w")로 엽니다. with 문을 사용하면 파일을 자동으로 닫아줍니다.
  2. line1 = "aaa"line2 = "bbb": 파일에 쓸 두 개의 문자열을 정의합니다.
  3. f.write(line1): 문자열 line1을 파일에 씁니다. 반환값은 쓰여진 문자 수입니다. 이 경우, 3자를 씁니다.
  4. f.write(line2): 문자열 line2를 파일에 씁니다. 반환값은 쓰여진 문자 수입니다. 이 경우, 3자를 씁니다.
  5. with open('output3.txt') as f:: “output3.txt” 파일을 읽기 모드로 엽니다.
  6. for line in f: print(line): 파일의 각 줄을 순회하면서 출력합니다. 결과는 aaabbb입니다.

Exercises

  • (1) 파일을 읽고 파일의 내용을 (줄별로) 모두 대문자로 출력하는 프로그램을 작성하십시오. 프로그램을 실행하면 다음과 같이 보일 것입니다:
$ python shout.py
Enter a file name: mbox-short.txt
FROM STEPHEN.MARQUARD@UCT.AC.ZA SAT JAN 5 09:14:16 2008
RETURN-PATH: <POSTMASTER@COLLAB.SAKAIPROJECT.ORG>
RECEIVED: FROM MURDER (MAIL.UMICH.EDU [141.211.14.90])
    BY FRANKENSTEIN.MAIL.UMICH.EDU (CYRUS V2.3.8) WITH LMTPA;
    SAT, 05 JAN 2008 09:14:16 -0500
  • (정답)
# shout.py
file_name = input("Enter a file name: ")

try:
    with open(file_name, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip().upper()
            print(line)
except:
    print("Invalid File Name!")
    exit()
  • (2) 아래 조건을 만족하는 프로그램을 작성하세요.
- 사용자로 부터 파일 이름을 입력 받습니다.
- 파일을 읽어서 아래와 같은 라인을 찾습니다:
    - X-DSPAM-Confidence: 0.8475
- 해당 라인을 카운트(count) 하고 부동소수점을 추출하여 합계를 만듭니다.
- 파일을 다 읽으면 평균 spam confidence를 출력합니다.
    - Enter the file name: mbox.txt
      Average spam confidence: 0.894128046745
    - Enter the file name: mbox-short.txt
      Average spam confidence: 0.750718518519
  • (정답)
# spam.py
file_name = input("Enter the file name: ")

try:
    with open(file_name, "r", encoding="utf-8") as f:
        count = 0
        total_spam_confidence = 0

        for line in f:
            if line.startswith("X-DSPAM-Confidence"):
                confidence = float(line.split(":")[1])
                total_spam_confidence += confidence
                count += 1

        if count > 0:
            average_spam_confidence = total_spam_confidence / count
            print(f"Average spam confidence: {average_spam_confidence}")
        else:
            print("No 'X-DSPAM-Confidence:' lines found.")
except FileNotFoundError:
    print("File not found. Please check the file name and try again.")

파이썬 기초 강좌: 8. 리스트 예제와 실습 (Python Basics – List Examples and Exercises)

Leave a Comment