IT

[코딩온] 신재생에너지 IoT 개발자 입문_ 파이썬13

혈중당부족 2026. 2. 3. 18:55

15 파일 입출력

저장 장치에 저장된 파일을 읽어오거나 저장하는 작업

하드디스크에  저장된 파일 불러오거나 데이터를 파일에 저장하는 경우를 말한다.

 

여기서 말하는 입출력 뜻은

입력(INPUT) 파일로부터 데이터 읽어온다.

출력 (OUTPUT) 데이터를 파일로 저장(기록)한다.

 

open() : 파일 열기 함수
open("파일 경로", mode = "r", encoding="원하는 인코딩 - utf8")
open으로 파일을 읽으면 '파일 객체'를 반환
 
여기서 말하는 인코딩이란?
컴퓨터가 저장하고 처리할 수 있는 이진수로 바꾸는 방식이다. 서로 다르면 한글 깨짐 현상 처럼 깨지기도 하고 Python의 기본 인고딩은 UTF-8 이다. 

 
실습때 r, w, a 위주로 사용했다.

f
 = open("example.txt", "w", encoding="utf-8"
 
파일에서 작성하기 위함이므로 'w' 사용
f.write("파이썬 파일 입출력 예제\n")
f.write("파이썬 공부")

close(): 파일 닫기
열린 파일을 닫아 시스템 자원을 해제함.
 
f.close()
 
하는 이유: 닫지 않으면 시스템 자원이 해제되지 않아 데이터 누수 발생 가능성 있다.
어떤 경우에는 다른 프로그램에 접근하지 못할 수 있다. (충돌)
계속 켜둔 채로 냅둘 경우 자원 사용이 계속 증가할 수 있다.
 
 
파일 읽기
read(): 전체 내용을 한번에 읽기.
f = open("example.txt", "r", encoding="utf-8")
content = f.read()
print(content)
f.close()

readlin() :한줄 씩 순차적으로 읽기
f = open("example.txt", "r", encoding="utf-8")
line1 = f.readline()
line2 = f.readline()

print("첫번 째 줄", line1)
print("두번 째 줄", line2)
f.close() #close로 계속 닫아주는 중.

 

for문으로 읽기
f = open("example.txt", "r", encoding="utf-8")
for line in f:
    print(line.strip())
f.close()

readlines() 모든 줄을 한번에 리스트로 읽기.

f = open("example.txt", "r", encoding="utf-8")
contents = f.readlines()
print(contents)
f.close()

tell () 현재 읽고 있는 위치(바이트)를 반환

f = open("example.txt", "r", encoding="utf-8")
print("처음 위치", f.tell()) << 일반적으로 0
f.read(5)
print("바이트 5 미만 후 읽은 위치", f.tell)
f.close()
 
한글은 UTF- 8 인코딩시 1글자당 3바이트일 수 있다.
 

seek() : 파일 포인터 위치로 이동

f = open("example.txt", "r", encoding="utf-8")
print(f.read(10)) #10바이트를 읽기
f.seek(0)#10 바이트 읽기ㅡ 맨 처음으로 가기
print(f.read())
f.close()
 
텍스트를 반복해서 읽거나, 중간 위치로 갈 때 사용한다.
 

파일 쓰기
with open("with_example.txt", "w", encoding="utf-8") as f1:
    f1.write("with문으로 작성한 파일이에요\n")
    f1.write("파일 입출력 완료")
 
\n은 줄바꿈 처리. 여러 줄을 작성할 때 직접 추가해야 한다. 
 
w 모드 : 덮어 쓰기
파일이 존재하면 기존 내용을 전부 삭제하고 새로 작성한다. 파일이 없으면 새로 생성.
 
f = open("example.txt", "w", encoding="utf-8")
f.write("이전 내용은 삭제되고 새로 작성됩니다.\n")
f.close()
 
a 모드 : 추가 쓰기
f = open("example.txt", "a", encoding="utf-8")
f.write("\n추가한 내용입니다.")
f.close()

 

 

 

주로 파일 작성 시 with 문법을 사용한다. 자동으로 파일 닫아주기 때문에 안전한 처리를 할 수 있다.

 

 

 

 

이를 활용한 예제

파일에서 랜덤 추출
import random

with open("words.txt", "w", encoding="utf-8") as f1:
    words = [
        "apple", "banana", "orange", "grape", "lemon",
        "peach", "melon", "cherry", "plum", "pear",
        "school", "friend", "family", "flower", "garden",
        "window", "bottle", "pencil", "summer", "winter",
        "happy", "future", "travel", "animal", "market",
        "doctor", "planet", "energy", "nature", "memory"
    ]
    for i in words:
        f1.write(i + "\n")


with open("words.txt", "r", encoding="utf-8") as f1:
    data = f1.readlines()
    for i in range(5):
        word = random.choice(data).strip()
        print(word)


입력 받아 파일 쓰기
with open("with_example.txt", "a", encoding="utf-8") as f1:
    while True:
        text = input("저장할 내용을 입력해주세요(종료 : z)")
        if text == "Z" or text == "z":
            break
        f1.write(text + "\n")
 
 
예제를 통해 실습 과제로
명부 작성, 명부 통해 로그인 기능 구현, 로그인 성공시 추가 정보 입력 과정을 작성 하는데
로그인 기능 구현까지 일단 시도 한 코드는 이랬다. 
 
회원에 대한 이름, 비밀번호 입력 받기 위해 사용자로부터 (파일 쓰기모드)로 생성
저장된 회원 명부를 출력(파일 읽기 모드)
 
user = []
with open("member.txt", "a", encoding="utf-8") as f2:
    for m in range(3):
        user_name = input(f"{m + 1} 회원명 입력해주세요: ")
        user_pass = input(f"{m + 1} 비밀번호 6자 입력해주세요: ")
        f2.write(f"회원 {user_name} 번호 {user_pass} \n")
        user.append((user_name, user_pass))


with open("member.txt", "r", encoding="utf-8") as f2:
    members = f2.readlines()
    print(members)


>>회원 명부를 통해 로그인 기능 구현
이름. 비밀번호를 각각 입력 받게 하고 회원 명부에서 한줄 씩 검사해서 성공/ 실패 출력
 
>> 근데 이거 파일 입출력 어떻게 정보 고정시키냐...
with open("words.txt", "r", encoding="utf-8") as f2:
    user_count = 0
    for line in f2:
        line = line.strip()
        user_name, user_pass = line.split(":")
        user_name = user_name.strip()
        user_pass = user_pass.strip()

    while user_count < 3 :
        id_input = input("이름을 입력하세요.: ")
        pw_input = input("비밀번호를 입력하세요.: ")

        if id_input == user_name and pw_input == user_pass:
            print("로그인 성공")
            user_count += 1
        else:
            print("로그인 실패")

    if user_count == 3:
        print("전원 로그인 됐습니다.")

 

이후 로그인 성공시 사용자에게 전화번호 입력 받기

>받은 번호는 다른 파일에서 이름과 전화번호 기록

>새로운 사람이 로그인 성공시 전화번호 추가 기록

>이미 존재하는 사람이 로그인 시 전화번호 수정

 

여기까지 구현하지 못하고 종료했다. 그리고 아래는 실습 답안으로 구현한 코드. (참고) 

더보기
#모범 답안
import os
#os 모듈 갖고 온다. 운영 체제와 상호 작용하는 기능 제공
#파일 및 디렉토리 관리하기 목적으로.

if os.path.exists("member.txt"): #경로의 존재 확인 명령어.
    print("member.txt가 이미 존재합니다. 회원 등록을 건너뜁니다.\n")
else: #파일 없을 시 생성해서 추가하기 위한 과정
    with open("member.txt", "w", encoding="utf-8") as f:
        for i in range(3):
            name = input(f"{i+1}번째 회원의 이름: ")
            password = input(f"{i+1}번째 회원의 비밀번호: ")
            f.write(f"{name},{password}\n")
       
print("\n[회원 명부 저장 완료]\n")

with open("member.txt", "r", encoding="utf-8") as f:
    members = f.readlines()
    print(members)

# 로그인 과정
input_name = input("로그인 - 이름을 입력하세요: ")
input_password = input("로그인 - 비밀번호를 입력하세요: ")

login = False #로그인은 '거짓'으로 정의한다.
#텍스트 파일의 정보를 할당해야 함.
#로그인 성공하면 반복문을 탈출한다.(break 사용)
with open("member.txt", "r", encoding="utf-8") as f:
    for line in f: #한줄 씩 갖고와서 비교하고자 for문 사용.
        name, password = line.strip().split(",") #,를 기준으로 리스트로 반환해서 출력.
        print(line.strip().split(",")) #리스트 형태로 반환되어 나옴. ['QWER','001234']
        if input_name == name and input_password == password:
            login = True
            break

#로그인 성공시 전화번호 등록/ 수정
if login:
    print("\n로그인 성공!")

    #기존 전화번호 데이터 로드
    phone_data = {} #딕셔너리 자료형 생성, 빈 걸로 만듬.

    if os.path.exists("member_tel.txt"): #파일 존재 유무 확인
        with open("member_tel.txt", "r", encoding="utf-8") as f: #존재가 있을 경우에 실행
            for line in f:
                name, phone = line.strip().split(",")
                phone_data[name] = phone #name 키값 폰이 밸류 값 딕셔너리
    print(phone_data)
    #파일이 있어서 정보를 확인하고, 그걸 딕셔너리에 할당. 그렇기에 phone_data를 출력하면 정보가 나온다.

    #전화번호 입력, if 바깥이므로 상관 없이 실행.
    new_phone = input(f"{input_name}님의 전화번호를 입력하세요: ")

    #전화번호를 딕셔너리로 추가한 것이라 파일 닫으면 사라지므로
    #파일 불러와서 작성해야 데이터 저장이 된다. (파일 갱신)
    # 추가 또는 수정
    if input_name in phone_data: #입력한 값과 기존 정보와 비교.
        print("기존 전화번호 수정")
    else:
        print("전화번호 새로 추가")
   
    phone_data[input_name] = new_phone
    #딕셔너리는 해당 키값이 있으면 밸류를 수정. 없으면 추가.
   
    # 전화번호 파일 갱신
    with open("member_tel.txt", "w", encoding="utf-8") as f:
        for name, phone in phone_data.items():
            f.write(f"{name},{phone}\n")
           
    print("전화번호 저장 완료!")
else:
    print("\n로그인 실패!")

 

바이너리 파일 읽고쓰기

 

 

import os

#바이너리 파일 열기
with open('./Python/images/ㄱㄴㅍㄱ.jpeg','rb') as f: #현재 디렉토리(.=PYTHON_WORKSPACE)/폴더명(Python)- 라는 뜻
    img = f.read()
    print(img)
 
원본 이미지 읽기 코드

#바이너리 파일 쓰기
with open("./Python_workspace/images/ㄱㄴㅍㄱ_copy.jpeg','wb'") as f:
    f.writh(img)
복사된 이미지를 새로운 파일로 저장하는 코드

# pickle 모듈
# 객체의 형태를 유지하면서 파일에 저장하고 불러올 수 있음
이때 객체는 리스트나 딕셔너리등의 자료 구조도 포함된다.

import pickle

#리스트, 딕셔너리 파일 저장
with open('pickle.txt','wb') as f:
    li = ['dog','cat'] #리스트 형식
    dic = {1: 'dog', 2: 'cat'} #딕셔너리 양식 {}

    pickle.dump(li, f)
    pickle.dump(dic, f)

#읽기
with open('pickle.txt','rb') as f:
    li = pickle.load(f)
    dic = pickle.load(f)

    print(li, dic) #['dog', 'cat'] {1: 'dog', 2: 'cat'} 로 나옴.
 
 
 

 

16 예외처리

 

프로그램이 예기치 않게 종료되는 것을 방지하고자 예외 처리 사용한다. 

 

예외 처리 기본 문법
try:
    예외가 발생할 수 있는 코드
    pass
except:
    예외가 발생했을 때 실행할 코드
    특정 에러를 지정 가능
    pass

 


예외 종류
1. 인덱스 에러
 리스트 인덱스 범위 오류
shop = ['반팔','청바지','이어폰','키보드']
print(shop[2])
print(shop[10]) #IndexError: list index out of range
print("예외 처리")

2.valueError
 부적절한 값을 가진 인자를 받았을 때 발생
#number = int("help") #ValueError: invalid literal for int() with base 10: 'help'
#print(shop.index("x")) #ValueError: list.index(x): x not in list < 리스트에 x라는 인자가 없다란 뜻

3.ZeroDivisionError
 0으로 나눌 때 발생
#print(5/ 0) ZeroDivisionError: division by zero

4. NameError
존재하지 않는 변수를 호출할 때
#print(x) NameError: name 'x' is not defined < x 정보가 없다.

5. FileNotFountError
 존재하지 않는 파일을 호출할 때
#file = open('test.txt') #FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'

 

1 단일 except

try:
    num = int(input("숫자를 입력하세요: "))
    print(10 / num)
except:
    print("예외 발생")
# 모든 에러를 "예외 발생"으로 띄워버림
 
 
2 특정 예외처리
 
try:
    num = int(input("숫자를 입력하세요: "))
    print(10 / num)
except ValueError as e:
    print("숫자가 아닙니다.",e)
except ZeroDivisionError as e:
    print("0으로 나눌 수 없습니다.",e)
# 여러 예외를 각각 처리해서 달리 출력함.

 

 

예외 처리 구조
 
try:
    #예외가 발생할 수 있는 코드
    pass
except 오류내용1:
    #예외가 발생했을 때 실행할 코드
    #특정 에러를 지정 가능
except 오류내용2:
다중 except라고 한다.
else
    #예외 없는 경우에 실행
finally:
    #예외 발생 여부와 상관 없이 실행

 

 

이하 예외처리 관련 실습 1

더보기
#실습1
try:
    num = int(input("숫자를 입력하세요: "))
except ValueError as e:
    num = -1
finally:
    if num > 0 :
        print(f"{num}이 0보다 큽니다.")
    else:
        print("숫자가 아닙니다.")



#모범 답안
# 실습 1
answer = input('Enter a number: ')

try:
    num = int(answer)
except:
    num = -1

if num > 0:
    print('0보다 큽니다!')
else:
    print('숫자가 아닙니다!')

 

 

이하 예외처리 관련 실습 2

더보기
def calc(a,b,x):
    if x == '+':
        return a + b
    elif x == '-':
        return a-b
    elif x == '*':
        return a*b
    elif x == '/':
        if b == 0:
            print("0으로 나눌 수 없습니다")
        else:
            return a/b

while True:
    try:
        a = int(input("숫자를 입력하세요: "))
        b = int(input("숫자를 입력하세요: "))

    except ValueError as e:
        print("잘못 입력 했습니다.")

    x = input("계산 방법을 입력하세요: ")

    if x not in ['+','-','*','/']:
        print("잘못된 연산입니다.")
        continue

    break

r = calc(a,b,x)
print(f"{a}{x}{b} = {r}")



#모범 답안
# 실습 2
def print_result(n1, op, n2, result):
    print(f"{n1} {op} {n2} = {result}")

while True:
    try:
        num1 = float(input("첫 번째 숫자: "))
        op = input("연산자(+ - * /): ")
        num2 = float(input("두 번째 숫자: "))
   
    if op not in ['+', '-', '*', '/']:
        raise ValueError("잘못된 연산자입니다.")
   
    if op == '/' and num2 == 0:
        raise ZeroDivisionError("0으로 나눌 수 없습니다.")
   
    # 계산
    if op == '+':
        result = num1 + num2
    elif op == '-':
        result = num1 - num2
    elif op == '*':
        result = num1 * num2
    else:
        result = num1 / num2
        print_result(num1, op, num2, result)
        break
    except ValueError:
        print("입력이 잘못되었습니다. 다시 입력하세요.\n")
    except ZeroDivisionError as e:
        print(e)
        print("다시 입력하세요.\n")
    except Exception:
        print("알 수 없는 오류가 발생했습니다.\n")

 

 

이렇게 파이썬 배웠던 부분을 전부 올렸다. 띄엄띄엄 해서, 남은 것들을 어디서까지 할 수 있을지 모르나 일단 달려봐야 아는 법이니까. 파이썬 기본 구조, 양식을 알았으니 다른 프로그램 사용할 때도 골자가 이해 안 가거나, 모른다. 하지 않고 접근할 수 있게 된 기분이었다. 특히 조건문, 반복문은... 질리도록 보지 않을까 싶다.