yuns

파일 입출력 본문

goorm 수업 정리/파이썬

파일 입출력

yuuuun 2021. 8. 6. 14:10
반응형

File open

  • File descriptor를 열기 위하여 open 내장함수를 사용
fd = open("file name", "접근 모드", encoding="utf8")
fd.close()
접근 모드 설명
r 읽기 모드 - 파일을 텍스트 형태로 읽을 때 사용
rb 이진 읽기 모드 - 파일을 바이너리 형태로 읽을 때 사용
w 쓰기 모드 - 파일을 텍스트 형태로 쓸 때 사용
wb 이진 쓰기 모드 - 파일을 바이너리 형태로 쓸 때 사용
a 추가 모드 - 파일의 마지막에 새로운 텍스트를 추가할 때 사용

File read

  • Read method로 파일 읽기 가능
fd = open("test.txt", "r")
contents = fd.read()
fd.close()

print(contents)
  • file descriptor 닫는 것을 깜빡할 때가 많기 때문에 context manager 형태로 사용할 것
    • with <ContextManager> as <ReturnValue>구문
with open("text.txt", "r") as fd:
    cotents = fd.read()
    
print(contents)

줄 단위로 잘라서 읽기, \n가 사라지는 것은 아님 abc\nbc\d형태로 추출됨

contents = []
with open("text.txt", "r") as f:
    for sentence in f:
    contents.append(sentence)
print(contents)

전체를 읽어 줄단위로 잘라서 반환 -> readlines

with open("text.txt", "r") as f:
    contents = f.readlines()
print(contents)

File Write

with open("text.txt", "w") as fd:
    for i in range(10):
        fd.write(f"{i + 1} 번째 문장\n")
with open("text.txt", "w") as fd:
    fd.writelines(f"{i + 1}번째 줄입니다\n" for i in range(10))
i = 10
#append  모드
with open("text.txt", "a") as fd:
     fd.write("내용을 추가합니다.\n")
     fd.writelines(f"{i + 1}번째 줄입니다.\n" for i in range(i, i + 10))

Directory

  • os library로 플랫폼의 독립적인 폴더 생성 가능
  • 파이썬에서는 '/'로 폴더를 나타냄
import os
os.mkdir("test") #이미 폴더가 있으면 에러
if not os.path.isdir("test"):
    os.mkdir("test")
    
# 하위 폴더 한번에 만들기, exist_ok옵션으로 이미 있을 경우 무시할지 확인
os.makedirs("test/a/b/c", exist_ok=True)

listdir 함수로 폴더 내 파일/하위 폴더 검색

import os
print(*[entry for entry in os.listdir('test')])

glob 라이브러리로 유닉스 스타일 경로명 패턴 확장 적용

import glob
print(*[entry for entry in glob.glob('test/*.txt')])

Pickle

파이썬 객체를 그대로 저장하고 싶을 경우

import pickle
seq = [[i * j for j in range(100)] for i in range(100)]

with open("test.pkl", "wb") as fd:
    pickle.dump(seq, fd)
del seq

with open("test.pkl", "rb" as fd:
    seq.pickle.load(fd)
print(seq[12][9])
  • 특징
    • 쓰기 쉽고 파이썬 개체를 그대로 저장한다
    • 파이썬에서만 사용할 수 있으며 보안 문제가 있다
  • Class Pickling
    • class객체를 직렬하기 위해서는 해당 클래스가 직렬화 가능 필요
      • 모든 속성(attribute)가 직렬화 가능 필요
    • 저장된 객체 pickle을 로드하고 싶다면 미리 해당 클래스 선언의 필요
      • 해당 클래스 정보가 없다면 역직렬화 불가

CSV

  • comma separate values
  • 표 데이터를 프로그램에 상관없이 쓰기 위한 데이터 형식
    • 필드를 쉼포로 구분한 텍스트 파일
    • 탭(TSV), 공백(SSV)등으로 구분하기도 함
  • Readlines로 읽을 수 있지만 구현이 귀찮음
  • csv라이브러리로 쉽게 읽고 쓰기 가능
import csv

with open('test.csv', 'r') as fd:
    reader = csv.reader(fd, 
        delimiter=',',                # 구분자 ,
        quotechar='"',                # 텍스트 감싸기 문자, 기본: "
        quoting = csv.QUOTE_MINIMAL   # parsing 방식, 기본: 최소 길이
    )
    
    for entry in reader:
        print(entry)
import csv

with open('test.csv', 'r') as fd:
    writer = csv.writer(fd, 
        delimiter=',',                # 구분자 ,
        quotechar='"',                # 텍스트 감싸기 문자, 기본: "
        quoting = csv.QUOTE_MINIMAL   # parsing 방식, 기본: 최소 길이
    )
    
    writer.writerow(['id', 'label'])
    writer.writerows([i, f'label_{i}'] for i in range(10))

JSON

  • 웹 언어인 javascript의 데이터 객체 표현 방식
    • 자료 구조 양식을 문자열로 표현
    • 간결하게 표현되어 사람과 컴퓨터 모두 읽기 편함
    • 코드에서 불러오기 쉽고 파일 크기 역시 작은 편
  • 그럼에도 parser 직접 작성은 매우 귀찮음
>>> import json
>>> with open('test.json', 'r') as fd:
        data = json.load(fd)
>>> print(data['hobbies'])
['reading', 'cinema', {'sports': ['volley-ball', 'snowboard']}]

>>> print(data['hobbies'][2]['sports'][0])
volley ball

test.json

{
  "ID":null,
  "name": "Doe",
  "first-name": "John",
  "age":25,
  "hobbies": [
    "reading",
    "cinema",
    {
      "sports": [
         "volley-ball",
         "snowboard"
      ]
    }
  ],
  "address": {}
}

 writing json

import json
obj = {
   "ID": None,
   "bool", False,
   "hobbies": {
      "sports": [
          "snowboard",
          "volley-ball"
      ]
    }
}
with open('test.json', 'w') as fd:
    json.dump(obj, fd)

XML

  • 데이터 구조와 의미를 설명하는 태그를 활용한 언어
  • <tag> </tag> 사이에 값이 표시
  • 문자열로 처리
  • <tag 속성 = 값> 형태로 태그에 속성 부여
  • HTML은 웹 페이지 표시를 위한 xml
  • 정규표현식으로 parsing 가능

Beautiful Soup

>>> conda install beautifulsoup4

Programming Setting

  • 실행할 때마다 필요한 설정 값
  • 한번 설정하면 수정을 잘 안하는 설정 값
import sys
print(sys.argv)
>>> python main.py
['main.py']

>>>python main.py --options 1234
['main.py', '--options', '1234]
  • Command-line Interface(CLI)에서 흔히 사용하는 방식
  • 파이썬에서는 sys 라이브러리의 arvs속성으로 접근

argparser

  • argparser 라이브러리를 사용
  • 인자 flag를 설정 가능하여 flag 별 입력 가능
  • 기본 값 설정 간으
  • help를 제공하여 사용자 편의 향상
  • type 설정 가능(문자열에서 변환)
import argparse

parser = argparse.ArgumentParser()
#parser.add_argument(<짧은 flag>, <긴 flag>)
parser.add_argument('-l', '--left', type=int)
parser.add_argument('-r', '--right', type=int)
parser.add_argument('--operation',
                    dest='op', 	#타겟 속성, 기본은 -- 없이
                    help='Set Operation',		# 인자 설명
                    default='sum')				# 기본 값

args = parser.parse_args()
print(args)

if args.op == 'sum':
    out = args.left + args.right
elif args.op == 'sub':
    out = args.left - args.right
    
print(out)

Config File

프로그램 실행 설정을 file에 저장

  • Section, key, value 값의 형태
    • [section] 설정 범주
    • [DEFAULT]- 기본 범주

configparser

  • 파이썬 기본 dictionary처럼 사용
  • 모든 것은 기본으로 str타입으로 처리
import configparser

config = configparser.ConfigParser()
config.read('test.cfg')

print(config.sections())

port = config['topsecret.server.com']['port']
print(type(port), port)
port = config['topsecret.server.com'].getint('port')
print(type(port), port)

for name, section in config.items():
    print(name)
    for key, value in section.items():
        print(key, value)
        
with open('test.cfg', 'w') as fd:
    config.write(fd)
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[bitbucket.org]
user = hg

[topsecret.server.com]
port = 50022
forwardx11 = no

Exception Handling

  • 프로그램 실행 중에는 다양한 예외/에러가 발생
  • 예외가 발생할 경우 대응 조치가 필요
try:
    <예외 발생 가능 코드>
except <예외 클래스>:
    <대응 코드>
for i in range(-5, 5):
    try:
        print(10 / i)
    except(ZeroDivisionError):
        print("Zero Division, skip the number,")

Built-in Exceptions

예외 이름 설명 발생 가능 예시
Index Error List의 Index 범위를 넘어감 list[1011]
NameError 존재하지 않는 변수를 호출 not_exist + 1
ZeroDivisionError 0으로 숫자를 나눔 10 / 0
ValueError 변환할 수 없는 문자열 / 숫자를 변환 float("abc")
FileNotFoundError 존재하지 않는 파일 호출 open("not_exist.txt", "r")

Exception Class

  • 파이썬 예외는 모두 BaseException 상속
    • 대부분 try로 최대 Exception단까지만 잡음
    • Exception Class를 상속하여 새로운 예외 생성 가능

Rasing & Referencing Exceptions

  • Raise 구문으로 예외 발생
    • raise <예외 객체>
  • As 구문으로 잡힌 에러를 참조 간으
    • except <예외 클래스> as <예외 객체>
try:
    while True:
        value = input("A B C 중 하나를 입력하세요: ")
        if len(value) == 1 and vlaue not in "ABC":
            raise ValueError("잘못된 입력입니다. 종료합니다.")
        print("선택된 옵션:" ,value)
            
except ValueError as e: #예외 객체 들고오기 가능
    print(e)

Assertion

  • 조건을 확인하여 참이 아닐 경우 AssertError 발생
    • assert <조건>
    • assert <조건>, <에러 메시지>
def add_int(param):
    assert isinstance(param, int), "int만 가능"
    return param + 1

try:
    print(add_int(10))
    print(add_int('str'))

except AssertionError as e:
    print(e)

Post-error Processing

1. 아무 구문 없음

try:
    functions()
escept SomeError as e:
    print(e, "예외 발생")
    
print("예외 이후")

2. else 구문

try:
    functions()
escept SomeError as e:
    print(e, "예외 발생")
else:
    print("예외 이후")

3. finally구문

try:
    functions()
escept SomeError as e:
    print(e, "예외 발생")
finally:
    print("예외 이후")
  아무 구문 없음 else 구문 finally 구문
예외 발생이 없을 경우 "예외 이후" 출력 "예외 이후" 출력 "예외 이후" 출력
SomeError 발생 "예외 발생" 출력
"예외 이후" 출력
"예외 발생" 출력 "예외 발생" 출력
"예외 이후" 출력
다른 예외 발생 프로그램 비정상 종료 프로그램 비정상 종료 "예외 이후" 출력
프로그램 비정상 종료
for i in range(5, -5, -1):
    try:
        value /= i
        
    except NameError:           #참조 에러 처리
        print("No value on value: set 0")
        value = 10
        
    except ZeroDivisionError:   #0 나누기 에러 처리
        print("Zero division: Skip")
    
    except Exception as e:      #처리되지 않은 에러 처리
        print(type(e), e)
        raise e                 #처리되지 않은 에러 재발생
    
    else:                       #예외가 발생하지 않는 경우
        print(value)
    
    finally:                    #모든 경우 출력
        print("Step")
No value on value: set 0
Step
2.5
Step
0.8333333333333334
Step
0.4166666666666667
Step
0.4166666666666667
Step
Zero division: Skip
Step
-0.4166666666666667
Step
0.20833333333333334
Step
-0.06944444444444445
Step
0.017361111111111112
Step

Logging

  • 프로그램이 일어나는 동안 발생했던 정보를 기록
    • 결과 처리, 유저 접근, 예외 발생 등
    • 기록된 로그 분석을 통한 디버깅 및 유저 패턴 파악
  • 기록 용도에 따른 차이
    • 용도에 따라 출력 형식 및 필터링 필요
  • 표출 방법
    • 표준 에러 출력 : 일시적, 기록을 위해서는 redirection 필요 및 구조화 필요
    • 파일 출력: 반 영구적, 매번 file description 을 열고 닫아야 함

logging module

import logging
logging.debug("디버깅")
logging.info("정보 확인")
logging.warning("경고")
logging.error("에러")
logging.critical("치명적 오류")
Level 설명 예시
DEBUG 상세한 정보, 보통 문제를 진단할 때만 사용 변수 A에 값 대입
함수 F호출
INFO 프로그램 정상 작동 중에 발생하는 이벤트 보고
상태 모니터링이나 결함 조사
서버 시작
사용자 user가 서버 제공
WARNING 예상치 못한 일이 발생하거나 가까운 미래에 발생할 문제에 대한 경고
대처할 수 있는 상황이지만 이벤트 주목 필요
문자열 입력 대신 숫자 입력 ->숫자로 변환 뒤 진행
인자로 들어온 리스트 길이가 안 맞음 -> 적당히 잘라서 사용
ERROR 오류가 발생하였으나 프로그램은 동작 가능
프로그램 일부 기능을 수행하지 못함
파일을 읽으려니 파일이 없음 ->사용자에게 알림
CRITICAL 심각한 오류 발생
프로그램 자체가 계속 실행되지 않을 수 있음
중요 파일이 없음
사용자가 강제 종료

Web Crawling

import requests

URL = 'https://www.naver.com"
response = requests.get(URL)

print(reponse.status_code)               # 결과 코드, 200이면 정상
print(response.text)
import requests
from bs4 import BeautifulSoup

URL = "https://sports.news.naver.com/index"
response = requests.get(URL)

soup = BeautifulSoup(
        response.text,
        'html.parser'
)

headline = soup.find(name='ul', attrs={'class': 'today_list'})
for title in headline.find_all(name='strong', attrs={'class': 'title'}):
    print(title.string)
반응형

'goorm 수업 정리 > 파이썬' 카테고리의 다른 글

정규표현식  (0) 2021.08.06
자료구조, 문자열, 정규표현식  (0) 2021.08.05
문법(2)  (0) 2021.08.04
문법  (0) 2021.08.03
Intro  (0) 2021.08.02
Comments