Day64

2021. 1. 13. 10:23교육과정/KOSMO

키워드 : 파이썬 예외 처리 / 파이썬 파일 읽고 쓰기 / 파이썬에서 csv, xml, json 사용하기 / 파이썬 정규식 표현 (유효성 검사 ) / 

 

****

 

1. 파이썬 예외 처리

 

    [에러와 예외]
    1. 에러
        문법적 오류
    2. 예외
        실행시 발생하는 오류로 예외가 발생하면 프로그램이 비정상 종료된다
    [예외처리]
    try:
        예외 발생 가능 문장들
    except Exception:
        예외가 발생한 후에 실행할 문장들
    else:
        예외가 발생하지 않았을 때 실행되는 문장들
    finally:
        예외 발생 여부와 상관없이 무조건 실행되는 문장들

    [참고] 파이썬 내장 예외
    https://docs.python.org/3/library/exceptions.html

※ 파이썬에서 else는 반복문, 조건문, 예외처리 등에서 사용할 수 있어 유용하다. 

 

 

(1) 예외처리 실습

 

    ① 10을 0으로 나눌 경우 예외가 발생하여 정상적으로 출력되지 않는다.  

10/0
print('종료')

# 실행결과
'''
ZeroDivisionError: division by zero
'''

 

    ② try ~ except Excception 을 사용하여 예외가 발생했을 때 수행할 작업을 지정할 수 있다. 

try:
     10/0
except Exception:
    print("예외")
    
# 실행결과
'''
예외
'''

 

    ③ except Excception 에 as 를 사용하여 예외가 발생했을 때 에러 내용을 출력할 수 있다. 

try:
     10/0
except Exception  as e:
    print("예외:", e)
else:
    print("예외없음")    

# 실행결과
'''
예외: division by zero
'''

 

    ④ try ~ except Excception ~ else 를 사용하여 예외가 발생하지 않고 정상 처리되었을 때 

        수행할 작업을 지정할 수 있다. 

try:
     10/1
except Exception  as e:
    print("예외:", e)
else:
    print("예외없음")

# 실행결과
'''
예외없음
'''

 


2. 파이썬 파일 읽고 쓰기

 

   @ 파일 읽고 쓰기
       - 파일을 읽고 쓰기 전에 파일을 열어야 한다
       - fileObj = open ( filename, mode )
   @ mode 첫번째 글자 - 작업 표시
            r(read)  : 파일 읽기
            w(write) : 파일 쓰기 ( 파일이 없으면 생성하고 파일이 있으면 덮어쓴다 )
            x(write) : 파일 쓰기 ( 파일이 없을 때만 생성하고 쓴다 )
            a(append) : 파일 추가 ( 파일이 있으면 파일의 끝에서부터 추가하여 쓴다 )
   @ mode 두번째 글자 - 파일 타입
            t : 텍스트(text) 타입 ( 기본값 )
            b : 이진(binary) 타입
      두번째 글자가 없으면 텍스트 타입이다.
   @ 한글처리는 이전에 사용을 했으면 하고, 사용하지 않았을 경우엔 적용하지 않아야 한다. 
       한글처리는 모든 파일에 무조건 하지 않고 필요한 경우에만 한다. 
             encoding='utf-8' : 한글
   @ 파일 닫기
       - 파일을 열고 사용 후에는 반드시 닫아야 한다.
       - 간단한 파일의 경우 별다른 문제가 없으나, 
         다수의 파일로 작업할 경우, 원치 않는 데이터 처리가 발생할 수 있기 때문에 필요한 작업 직후 닫아준다. 
         (통로는 기본적으로 바로 닫아주기 ! )
       - 파일 객체를 자동으로 닫는 with 구문을 많이 사용한다. 

 

(1) mode의 첫번째 글자에서 ' r ' 을 기술하여 파일 읽기 작업을 할 경우

    ① 파일이 있을 경우

f = open('./data/data.txt', 'r', encoding='utf-8')

line = f.read()
print(line)

f.close()

# 실행결과
'''
안녕하세요 data.txt 파일입니다.
'''

 

    ② 파일이 없을 경우 ... 에러가 발생한다. 

f = open('./data/data2.txt', 'r', encoding='utf-8')

line = f.read()
print(line)

f.close()

# 실행결과
'''
FileNotFoundError: [Errno 2] No such file or directory: './data/data2.txt'
'''

 

(2) 예외처리를 적용시킨 (1) 의 상황

※ 예외가 발생한 상황에서는 open 자체가 정상적으로 수행되지 않기 때문에 close 할 필요가 없다. 
    따라서, else 로 정상처리되었을 때에 close 가 수행되도록 작성한다. 

 

    ① 파일이 있을 경우

try:
    f = open('./data/data.txt', 'r', encoding='utf-8')
except Exception as e:
    print('예외발생', e)
else:
    line = f.read()
    print(line)
    f.close()
finally:
    print('종료합니다.')

# 실행결과
'''
안녕하세요 data.txt 파일입니다.
종료합니다.
'''

 

    ② 파일이 없을 경우

try:
    f = open('./data/data0.txt', 'r', encoding='utf-8')
except Exception as e:
    print('예외발생', e)
else:
    line = f.read()
    print(line)
    f.close()
finally:
    print('종료합니다.')

# 실행결과
'''
예외발생 [Errno 2] No such file or directory: './data/data0.txt'
종료합니다.
'''

 

(3) 반복문을 사용하여 파일을 한 줄씩 읽다가 더 이상 내용이 없을 경우 반복문을 빠져나가게 하기

     ※ readline( )은 한 줄을 읽어온다. 

try:
    f = open('./data/data.txt', 'r', encoding='utf-8')
except Exception as e:
    print('예외발생', e)
else:
    while True:
        line = f.readline()
        if not line: break
        print(line)
    f.close()
finally:
    print('종료합니다.')

 

(4) with 구문을 사용하면 파일을 열고 데이터를 읽는 작업이 끝난 뒤, 자동으로 파일 객체를 (close)닫아준다.  

with open('./data/data.txt', 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if not line: break
        print(line)
print('종료합니다')

# 실행결과
'''
안녕하세요 data.txt 파일입니다.
종료합니다
'''

 

(5) 파일을 한 번에 읽은 뒤 단어 수를 출력할 수 있다. 

with open('./data/data.txt', 'r', encoding='utf-8') as f:
    content = f.read()
    words = content.split()
    print('단어수=',len(words))
print('종료합니다')

# 실행결과
'''
단어수= 3
종료합니다
'''

3. 파이썬 파일 읽고 쓰기 - 연습문제

 

※ 다음 조건을 충족하는 함수 count_words 를 완성 후 정상적으로 출력되는지 확인한다. 

    함수 정의 : count_words
    인자 : filename

    인자로 받은 파일명을 open 하여 파일을 읽어서 단어를 수를 출력한다.
    존재하지 않는 파일명으로 예외가 발생해도 아무런 일을 하지 않는다

    ① 방법1

def count_words(filename):
    try:
        f = open('./data/'+filename, 'r', encoding='utf-8')
    except Exception as e:
        pass
    else:
        words = f.read().split()
        print(filename, ' 단어수=',len(words))
        f.close()

filenames = ['sample.xml', 'xxxx.xxx', 'temp.json']
for filename in filenames:
    count_words(filename)

# 실행결과
'''
sample.xml  단어수= 31
temp.json  단어수= 19
''''

print(filename, ' 단어수=', len(words)) 대신 return print(filename, ' 단어수=', len(words)) 를 사용할 수도 있다. 

    ② 방법 2

def count_words(filename):
    try:
        with open('./data/'+filename, 'r', encoding='UTF-8') as f:
            print(filename, ' 단어수=', len(f.read().split()))
    except Exception as e:
        pass

# 존재하지 않는 파일명도 있음
filenames = ['sample.xml', 'xxxx.xxx', 'temp.json']
for filename in filenames:
    count_words(filename)

# 실행결과
'''
sample.xml  단어수= 31
temp.json  단어수= 19
'''

 

    ③ 방법 3

def count_words(filename):
    try:
        f = open('./data/'+filename, 'r', encoding='UTF-8')
    except Exception as e:
        pass
    else:
        with f:
            print(filename, ' 단어수=', len(f.read().split()))


# 존재하지 않는 파일명도 있음
filenames = ['sample.xml', 'xxxx.xxx', 'temp.json']
for filename in filenames:
    count_words(filename)

# 실행결과
'''
sample.xml  단어수= 31
temp.json  단어수= 19
'''

4. 파이썬에서 csv 활용하기

 

※ 확장자명을 csv로 만들어두면 엑셀에서 읽을 수 있고, 다양한 작업이 가능하다. 

   단, 매우 큰 용량의 경우 엑셀로 처리가 불가능하기 때문에 이 경우에는 파이썬 등 다른 방법을 사용해야 한다. 

※ csv : common string value 로 평범한 문자열의 데이터를 저장하는 형식

 

(1) 리스트의 데이터를 csv로 저장하기

    ① csv 로 파일을 읽고 쓰기 위해서는 패키지를 import 해야 한다. 

import csv

 

    ② 저장할 데이터를 리스트 구조로 작성한다. 

data = [ [1,'김길동','책임'], [2,'박길동','연구원'], [3,'최길동','선임'] ]

 

    ③ imsi.csv 라는 이름으로 파일을 저장하도록 with 구문을 작성한다. 

    writer( ) : 데이터를 저장하기 위한 가상 통로를 얻어온다. 
    writerow( ) : 데이터를 한 줄식 보낸다. 
with open('./data/imsi.csv', 'wt', encoding='utf-8-sig') as f:
    c_out = csv.writer(f) 
    c_out.writerow(data) 
    엑셀은 ANSI 코드로 디코딩해야 하므로  encoding='utf-8-sig' 라고 작성한다. 

 

(실행결과)

※ csv 파일을 엑셀에서 열 때 한글이 깨질 경우, 

   파일 우클릭 - 메모장으로 열기 - 다른이름으로 저장 - 인코딩을 'ANSI'로 변경 후 저장

   → 엑셀에서 정상적으로 글씨 출력된다. 

 

 

(2) csv 파일의 리스트 데이터를 파이썬으로 읽어오기

data = []
with open('./data/imsi.csv', 'r', encoding='utf-8-sig') as f:
    cin = csv.reader(f)
    data = [row for row in cin if row]
print(data)

# 실행결과
'''
[["[1, '김길동', '책임']", "[2, '박길동', '연구원']", "[3, '최길동', '선임']"]]
'''

 

(+) 추가 ...... 컴프리핸션에서 조건문을 사용하지 않으려면, 

# newline 설정을 하지 않으면 한 줄마다 공백 있는 줄이 들어가버린다.
# 즉, [3, 최길동, 선임] 뒤에 공백 셀 하나가 생긴다.
# 따라서 newline='' 을 설정해준다.

data = [[1, '김길동', '책임'], [2, '박길동', '연구원'], [3, '최길동', '선임']]

with open('./data/imsi.csv', 'wt', newline='', encoding='UTF-8-sig') as f:
    cout = csv.writer(f)
    cout.writerow(data)
    
with open('./data/imsi.csv', 'r', encoding='utf-8-sig') as f:
    cin = csv.reader(f)
    data = [row for row in cin] 
print(data)

 


5. 파이썬 연습문제 - 파일처리와 예외처리 

 

(1) 다음 코드의 실행 결과를 쓰시오.

try:
    for i in range(1, 7):
        result = 7 // i
        print(result)
except ZeroDivisionError:
    print("Not divided by 0")
finally:
    print("종료되었습니다.")

답 : 

7
3
2
1
1
1
종료되었습니다.

 

(2) 다음 코드를 실행했을 때, 가장 마지막에 출력되는 값은?

sentence = list("Hello Gachon")
while (len(sentence) + 1):
    try:
        print(sentence.pop(0))
    except Exception as e:
        print(e)
        break

o         n         ③ h         ④ c        pop from empty list

답 : ⑤

(풀이)

sentence를 출력하면 ['H', 'e', 'l', 'l', 'o', ' ', 'G', 'a', 'c', 'h', 'o', 'n'] 이다. 
len(sentence) 는 12가 되고 while문에 들어가는 수는 12+1 인 13 이된다. 
pop(0) 함수에 의해 0번째 글자를 뽑는 작업을 13번 반복하는데
12번까지는 정상적으로 수행되지만, 13번째에는 list 에 남아있는 데이터가 없어서 
pop from empty list 예외가 발생한다. 

       

(3) 다음 각각의 예외 처리에 적합한 내장 예외(built-in exception)를 순서대로 실행한 결과값이 바르게 짝지어진 것은?
(

alist = ["a", "1", "c"]
blist = ["b", "2", "d"]
for a, b in enumerate(zip(alist, blist)):
    print(b[a])

()

alist = ["a", "1", "c"]
blist = ["b", "2", "d"]
for a, b in enumerate(zip(alist, blist)):
    print(a/int(b[0]))

 NameError, ValueError                IndexError, NameError
ZeroDivisionError, ValueError        IndexError, ValueError           NameError, IndexError

답 : ④

(풀이)

Index Error : 인덱싱 범위를 넘어선 값이 주어졌을 때 발생하는 에러
Value Error : 데이터 타입이 맞지 않을 때 발생하는 에러
Name Error : 변수가 정의되어 있지 않을 때 발생하는 에러
ZeroDivisionError : 어떠한 수를 0으로 나눌 때 발생하는 에러
zip(alist, blist)의 결과는 
   ('a', 'b')
   ('1', '2')
   ('c', 'd')
enumerate(zip(alist, blist)) 의 결과는
   (0, ('a', 'b'))
   (1, ('1', '2'))
   (2, ('c', 'd'))
for a, b in enumerate(zip(alist, blist)) 의 경우
    a       b
   (0, ('a', 'b'))
   (1, ('1', '2'))
   (2, ('c', 'd'))    
   
b[a] 는 ('a', 'b')에서 0번째를 출력하면 'a' 
        ('1', '2')에서 1번째를 출력하면 '2'
        ('c', 'd')에서 2번째를 출력하면 IndexError: tuple index out of range
a/int(b[0]) 는 ('a', 'b') 에서 b[0] 는 a 이므로 0/a 의 결과는 ValueError: invalid literal for int() with base 10: 'a'
               ('1', '2') 에서 b[0] 는 1 이므로 1/1 의 결과는 1
               ('c', 'd') 에서 b[0] 는 c 이므로 2/c 의 결과는 ValueError: invalid literal for int() with base 10: 'c'

 

(4) 다음 중 예외(exception)의 이름과 내용이 잘못 짝지어진 것은?
    ① ZeroDivisionError: 0으로 숫자를 나눌 때
    ② ValueError: 변환할 수 없는 문자/숫자를 변환할 때
    ③ IndexError: 리스트의 인덱스 범위를 넘어 갈 때
    ④ SyntaxError: 조건문이나 변수에 오탈자가 존재할 때
    ⑤ NameError: 존재하지 않은 변수를 호출할 때

답 : ④ 

(풀이)

Syntax Error 는 파이썬 문법에 맞지 않는 표현이 있을 경우 발생하는 구문 오류이다. 

 

 

(5) 파일의 종류에 대한 설명으로 틀린 것은?
    ① 바이너리 파일은 컴퓨터만 이해할 수 있는 형태인 이진법 형식으로 저장된 파일을 말한다.
    ② 텍스트 파일의 예로 HTML, 파이썬 코드 파일 등을 들 수 있다.
    ③ 바이너리 파일은 해당 확장자에 대한 파일을 열 수 있는 프로그램이 필요하다(엑셀, 워드 등).
    ④ 텍스트 파일의 경우 컴퓨터는 텍스트 파일 형태 그대로 처리가 가능하다.
    ⑤ 텍스트 파일은 사람도 이해할 수 있는 형태인 문자열 형식으로 저장된 파일을 말한다.

답 :

(풀이)

컴퓨터는 텍스트 파일을 이진법 형식으로 변환한 뒤 처리한다. 

 

(6) 다음 코드의 실행 결과를 쓰시오.

for i in range(3):
    try:
        print(i, 3// i)
    except ZeroDivisionError:
        print("Not divided by 0")

답 : 

Not devided by 0
1 3
2 1

 

(7) 다음 코드는 파이썬에서 ‘i_have_a_dream.txt’ 파일을 읽어오는 코드이다.
   같은 기능을 하는 코드를 with 구문과 함께 사용하여 작성하시오.

f = open("i_have_a_dream.txt", "r")
contents = f.read()
print(contents)
f.close()

답 : 

with open("i_have_a_dream.txt", "r") as f:
    contents = f.read()
    print(contents)

 

(8) 바이너리 파일과 텍스트 파일에 대한 설명으로 틀린 것은?
    ① 텍스트 파일은 사람도 이해할 수 있는 형태로 저장된다.
    ② 메모장에 저장된 파일, HTML 파일, 파이썬 코드 파일 등은 모두 텍스트 파일이다.
    ③ 텍스트 파일은 컴퓨터만 이해할 수 있는 형태인 이진() 형식으로 저장된 파일이다.
    ④ 엑셀 파일, 워드 파일 등을 바이너리 파일이라고 부른다.
    ⑤ 모든 텍스트 파일도 실제는 바이너리 파일로 아스키/유니코드 문자열 집합으로 저장된다.

답 : ③

(풀이)

컴퓨터만 이해할 수 있는 파일은 바이너리 파일이다. 

 


6. 파이썬에서 xml 활용하기

 

※ xml : 데이터를 안정적인 구조로 주고 받기 위해 사용한다. 

 

(1) xml 파일을 사용하기 위해서 패키지를 import 한다. 

import xml.etree.ElementTree as et

 

(2) ElementTree( ) 함수를 사용하여 xml 파일을 읽고 출력한다. 

    ① ElementTree( ) 함수에 들어가는 인자는 키워드인자이므로 타입을 명시해줘야 한다. (위치인자가 아님)

    ② getroot( ) 함수는 xml 문서에서 최상위 루트 태그를 가져온다. 

import xml.etree.ElementTree as et

tree = et.ElementTree(file = './data/temp.xml')
root = tree.getroot()
print('root : ', root)

# 실행결과
'''
root :  <Element 'employees' at 0x00000256B0D73868>   # ... 최상위 루트 태그는 employees 
'''

 

(3) root.tag 로 루트 태그만 출력할 수 있다. 

import xml.etree.ElementTree as et

tree = et.ElementTree(file = './data/temp.xml')
root = tree.getroot()
print('root tag : ', root.tag)

# 실행결과
'''
root tag :  employees
'''

 

(4) 최상위 태그를 반복문의 집합요소로 하여 출력하면 하위에 있는 자식 태그를 출력할 수 있다. 

import xml.etree.ElementTree as et

tree = et.ElementTree(file = './data/temp.xml')
root = tree.getroot()

for child in root:
    print(child.tag)

# 실행결과
'''
employee
employee
employee
'''

 

(5) root의 자식에서 다시 한 번 자식을 출력하면 하위의 태그를 출력할 수 있다. 

import xml.etree.ElementTree as et

tree = et.ElementTree(file = './data/temp.xml')
root = tree.getroot()

for child in root:
    for jason in child:
        print(jason.tag, end=' ')

# 실행결과
'''
no name job no name job no name job 
'''

 

(6) .tag에서는 태그를, .test에서는 태그 안에 들어있는 텍스트를 출력할 수 있다. 

import xml.etree.ElementTree as et

tree = et.ElementTree(file = './data/temp.xml')
root = tree.getroot()

for child in root:
    for jason in child:
        print(jason.tag, ':', jason.text)

# 실행결과
'''
no : 1
name : 김
job : 책임
no : 2
name : 박
job : 선임
no : 3
name : 이
job : 연구원
'''

 


7. 파이썬에서 json 활용하기

 

(1) json 파일을 사용하기 위해서는 패키지를 import 한다. 

import json

 

(2) temp.json 파일을 읽은 결과, 단순 문자열로 출력된다. 

f = open('./data/temp.json', 'r', encoding='utf-8')
data = f.read()
print(data)
print(type(data))           # <class 'str'>

# 실행결과
'''
{
  "박열":{
    "No":1,
    "Job": "선임"
  },
  "김원봉":{
  "No":2,
  
....

'''

 

(3) 읽어온 데이터가 json 구조를 가질 수 있도록 json.loads( ) 함수를 처리해준다. 

    출력결과는 딕셔너리 타입이 된다. 

import json

f = open('./data/temp.json', 'r', encoding='utf-8')
data = f.read()

items = json.loads(data)
print(items)
print(type(items))     

# 실행결과
'''
{'박열': {'No': 1, 'Job': '선임'}, '김원봉': {'No': 2, 'Job': '주임'}, '이순신': {'No': 3, 'Job': '연구원'}}
<class 'dict'>
'''

 

(4) 딕셔너리 구조를 갖는 items 에 print ( ) 함수를 적용하면 key에 해당하는 값만 출력된다. 

import json

f = open('./data/temp.json', 'r', encoding='utf-8')
data = f.read()

items = json.loads(data)
for item in items:
    print(item)   

# 실행결과
'''
박열
김원봉
이순신
'''

 

(5) 딕셔너리 구조를 갖는 items로부터 key 뿐만 아니라 value를 출력할 수 있다. 

     ① items[ ].get( ) 메소드를 사용

import json

f = open('./data/temp.json', 'r', encoding='utf-8')
data = f.read()

items = json.loads(data)
for item in items:
    print(item, items[item].get('No'), items[item].get('Job')) 

# 실행결과
'''
박열 1 선임
김원봉 2 주임
이순신 3 연구원
'''

 

    ② items( ) 함수를 사용하여 딕셔너리 구조를 튜플로 변환 후 추출

import json

f = open('./data/temp.json', 'r', encoding='utf-8')
data = f.read()

items = json.loads(data)
for item, values in items.items():      # items() 함수를 사용하여 튜플로 추출
    for i, v in values.items():
        print(i, v)

# 실행결과
'''
No 1
Job 선임
No 2
Job 주임
No 3
Job 연구원
'''

8. 파이썬에서 json 활용하기 - 연습문제

 

sample.json 파일을 읽어서 총 합계를 출력하기

import json

f = open('./data/sample.json', 'r', encoding='utf-8')
data = f.read()

fruits = json.loads(data)
print(fruits)

hap = 0
for fruit in fruits:
    price = fruits[fruit].get('price')
    cnt = fruits[fruit].get('count')
    hap += price * cnt
    print('{} {:2d}개 {:4d}원 (개당 {:3d}원)'.format(fruit, cnt, price * cnt, price))
print('총계 : {}원'.format(hap))

# 실행결과
'''
{'사과': {'price': 500, 'count': 3}, '망고': {'price': 200, 'count': 2}, '딸기': {'price': 400, 'count': 10}, '과자': {'price': 100, 'count': 10}, '커피': {'price': 10, 'count': 20}}
사과  3개 1500원 (개당 500원)
망고  2개  400원 (개당 200원)
딸기 10개 4000원 (개당 400원)
과자 10개 1000원 (개당 100원)
커피 20개  200원 (개당  10원)
총계 : 7100원
'''

 


9. 파이썬 정규식 표현

    # [참고] 파이썬 정규식 표현
            - https://docs.python.org/3/library/re.html
            - https://wikidocs.net/4308 > re

 

    # raw string
        - 문자열 앞에 r이 붙으면 해당 문자열이 구성된 그대로 문자열로 변환
a = 'abcdef\n'               # escape 문자열 : \ 이후에 미리 예약된 문자가 온다. 
b = r'abcdef\n'

print(a)
print(b)

# 실행결과
'''
abcdef

abcdef\n
'''

 

※ 패턴과 관련된 함수

    # 패턴과 소스를 비교하는 함수
    - (1) match() : 패턴의 일치여부 확인
                search와 유사하나, 주어진 문자열의 시작부터 비교하여 패턴이 있는지 확인
                시작부터 해당 패턴이 존재하지 않다면 None 반환
    - (2) findall() : 일치하는 모든 문자열 리스트 반환
                search가 최초로 매칭되는 패턴만 반환한다면, findall은 매칭되는 전체의 패턴을 반환
                매칭되는 모든 결과를 리스트 형태로 반환
    - (3) search() : 첫번째 일치하는 객체 반환
    - (+) split() : 패턴에 맞게 소스를 분리한 후 문자열 조각의 리스트 반환
    - (+) sub() : 주어진 문자열에서 일치하는 모든 패턴을 replace
                그 결과를 문자열로 다시 반환함
                count가 0인 경우는 전체를, 1이상이면 해당 숫자만큼 치환 됨

 

(1) match( ) : 패턴의 일치 여부 확인

    ① 별도의 정규식 표시가 없을 경우 원본 문자열의 시작부분부터 검사한다. 

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.match('We', msg)         # ... re.match('^We', msg) 와 같은 결과 ...^는 맨 앞을 뜻함
result2 = re.match('You', msg)       # ... re.match('^You', msg) 와 같은 결과

print(result)  
print(result2)

# 실행결과
'''
<re.Match object; span=(0, 2), match='We'>
None
'''

    → We 를 맨 앞에서 찾은 결과 match 되었다고 출력되고,

        You를 맨 앞에서 찾은 결과 match 가 되지 않아 None 이라고 출력된다. 

 

    ② match( ) 함수의 결과는 object 이기 때문에 찾은 단어를 출력하기 위해서는 group( ) 함수를 사용한다.

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.match('We', msg)
result2 = re.match('You', msg)

print(result.group())
# print(result2.group())        ........ 결과가 None 이기 때문에 에러 발생
if result2:
    print(result.group2())      # ...... 결과가 있을 때만 출력하도록 함

# 실행결과
'''
We
'''

 

    ③ 정규식을 적용하여 happy와 같은 문자열이 있는지 확인할 수 있다. 

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result1 = re.match('.*happy', msg)         # ... .은 문자가 일치함을, *은 0회 이상을 뜻함
result2 = re.match('.*2020', msg)

print(result.group())
if result:
    print(result.group()) 
print(result2.group())
if result2:
    print(result.group2()) 

# 실행결과
'''
<re.Match object; span=(0, 27), match='We are happy. You are happy'>
We are happy. You are happy
<re.Match object; span=(0, 43), match='We are happy. You are happy. Happy2019 2020'>
We are happy. You are happy. Happy2019 2020
'''

 

 

(2) findall( ) : 일치하는 모든 문자열 리스트 반환 

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.findall('happy', msg)
if result:
    print(result)
    
# 실행결과
'''
happy
'''

 

 

(3) search() : 첫번째 일치하는 객체 반환

               : 패턴이 어디 있던지 찾아낸다. 

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.search('happy', msg)
if result:
    print(result)
    
# 실행결과
'''
['happy', 'happy']
'''

 

 

(+) split() : 패턴에 맞게 소스를 분리한 후 문자열 조각의 리스트 반환

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.split('a', msg)
if result:
    print(result)   
    
# 실행결과
'''
['We ', 're h', 'ppy. You ', 're h', 'ppy. H', 'ppy2019 2020']
'''

 

 

(+) sub() : 주어진 문자열에서 일치하는 모든 패턴을 replace

import re

msg = 'We are happy. You are happy. Happy2019 2020'

result = re.sub('a', '@', msg)
if result:
    print(result)  
    
# 실행결과
'''
We @re h@ppy. You @re h@ppy. H@ppy2019 2020
'''

 


10. 파이썬 정규식 표현 - 연습문제

 

※ 다른 모든 함수들도 정규식 표현으로 추출 및 검색 가능

   # 기본 패턴
     - a, X, 9 등등 문자 하나하나의 character들은 정확히 해당 문자와 일치
       e.g) 패턴 test는 test 문자열과 일치
       대소문자의 경우 기본적으로 구별하나, 구별하지 않도록 설정 가능

     - 몇몇 문자들에 대해서는 예외가 존재하는데, 이들은 특별한 의미로 사용 됨
       . ^ $ * + ? { } [ ] | ( )

     - . (마침표) - 어떤 한개의 character와 일치 (newline(엔터) 제외)

     - \w - 문자 character와 일치 [a-zA-Z0-9_]
     - s - 공백문자와 일치
     - t, n, r - tab, newline, return
     - d - 숫자 character와 일치 [0-9]
     - ^ (시작), $(끝) :  각각 문자열의 시작과 끝을 의미
     - 가 붙으면 스페셜한 의미가 없어짐. 예를들어 .는 .자체를 의미 를 의미
    # [ ] 문자들의 범위를 나타내기 위해 사용
       - [ ] 내부의 메타 캐릭터는 캐릭터 자체를 나타냄
       - e.g)
       - [abck] : a or b or c or k
       - [abc.^] : a or b or c or . or ^
       - [a-d]  : -와 함께 사용되면 해당 문자 사이의 범위에 속하는 문자 중 하나
       - [0-9]  : 모든 숫자
       - [a-z]  : 모든 소문자
       - [A-Z]  : 모든 대문자
       - [a-zA-Z0-9] : 모든 알파벳 문자 및 숫자
       - [^0-9] : ^가 맨 앞에 사용 되는 경우 해당 문자 패턴이 아닌 것과 매칭
    #
     (1) 다른 문자와 함께 사용되어 특수한 의미를 지님
       - d : 숫자                  .........  [0-9] 와 동일
       - D : 숫자가 아닌 문자 .........  [^0-9] 와 동일
       - s : 공백 문자 (띄어쓰기, 탭, 엔터 등)
       - S : 공백이 아닌 문자
       - w : 알파벳대소문자, 숫자       .........  [0-9a-zA-Z] 와 동일
       - W : non alpha-numeric 문자  .........  [^0-9a-zA-Z] 와 동일
     (2) 메타 캐릭터가 캐릭터 자체를 표현하도록 할 경우 사용
       - .     , 
     # 반복패턴
     - 패턴 뒤에 위치하는 *, +, ?는 해당 패턴이 반복적으로 존재하는지 검사
       - '+' -> 1번 이상의 패턴이 발생
       - '*' -> 0번 이상의 패턴이 발생
       - '?' -> 0 혹은 1번의 패턴이 발생
     - 반복되는 패턴의 경우 greedy하게 검색 함, 즉 가능한 많은 부분이 매칭되도록 함
      - e.g) a[bcd]*b  패턴을 abcbdccb에서 검색하는 경우
        - ab, abcb, abcbdccb 전부 가능 하지만 최대한 많은 부분이 매칭된 abcbdccb가 검색된 패턴

 

    ① 소문자를 찾아서 반환

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[a-z]', msg)
if result:
    print(result)

# 실행결과
'''
['a', 'p', 'p', 'y', 'y', 'e', 'a', 'r', 'e', 'a', 'r', 'e', 's', 'o', 'h', 'a', 'p', 'p', 'y']
'''

   (+) 소문자를 1개만 찾을 경우

import re

msg = '2025 Happy year! We are so happy?'

result = re.search('[a-z]', msg)
if result:
    print(result.group())

# 실행결과
'''
a
'''

 

    ② 소문자가 아닌 것들을 찾아서 반환 (대괄호 안에 ^)

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[^a-z]', msg)
if result:
    print(result)

# 실행결과
'''
['2', '0', '2', '5', ' ', 'H', ' ', '!', ' ', 'W', ' ', ' ', ' ', '?']
'''

 

    ③ 대문자를 찿음

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[A-Z]', msg)
if result:
    print(result)
    
# 실행결과
'''
['H', 'W']
'''

 

    ④ +반복 옵셥으로 소문자를 연속해서 찾음 ( , 단어 )

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[a-z]+', msg)
if result:
    print(result)

# 실행결과
'''
['appy', 'year', 'e', 'are', 'so', 'happy']
'''

 

    ⑤ 소문자와 대문자를 단어 단위로 찾음

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[a-z]+', msg)
if result:
    print(result)
result = re.findall('[A-Z]+', msg)
if result:
    print(result)

# 실행결과
'''
['appy', 'year', 'e', 'are', 'so', 'happy']
['H', 'W']
'''

 

    ⑥ 숫자를 찾음

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[0-9]', msg)
if result:
    print(result)

# 실행결과
'''
['2', '0', '2', '5']
'''

 

    ⑦ +반복 옵션으로 숫자를 찾음

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[0-9]+', msg)  # ........ re.findall('\d+',msg) 과 동일
if result:
    print(result)

# 실행결과
'''
['2025']
'''

 

    ⑧ 소문자, 대문자, 숫자가 아닌 문자들 ( 공백문자나 특수문자 )

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('\W', msg)  # ........ re.findall('[^a-zA-Z0-9]', msg) 과 동일
if result:
    print(result)

# 실행결과
'''
[' ', ' ', '!', ' ', ' ', ' ', ' ', '?']
'''

 

    ⑨ 문자 숫자 _ 를 검색

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[\w_]', msg)
if result:
    print(result)

# 실행결과
'''
['2', '0', '2', '5', 'H', 'a', 'p', 'p', 'y', 'y', 'e', 'a', 'r', 'W', 'e', 'a', 'r', 'e', 's', 'o', 'h', 'a', 'p', 'p', 'y']
'''

 

    ⑩ 영문자 숫자 _가 아닌 것들 검색

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('[^a-zA-Z0-9_]', msg)
if result:
    print(result)

# 실행결과
'''
[' ', ' ', '!', ' ', ' ', ' ', ' ', '?']
'''

 

    ⑪ 숫자가 아닌 것들 검색

import re

msg = '2025 Happy year! We are so happy?'

result = re.findall('\D', msg)
if result:
    print(result)

# 실행결과
'''
[' ', 'H', 'a', 'p', 'p', 'y', ' ', 'y', 'e', 'a', 'r', '!', ' ', 'W', 'e', ' ', 'a', 'r', 'e', ' ', 's', 'o', ' ', 'h', 'a', 'p', 'p', 'y', '?']

'''

 


11. 파이썬 컴파일 (compile)

 

    # compile
     - 동일한 정규표현식을 매번 다시 쓰기 번거로움을 해결
     - compile로 해당표현식을 re.RegexObject 객체에 저장하여 사용가능

 

※ 패턴을 만들고 해당되는 데이터를 찾아 출력할 수 있다. 

    [\w-] : 문자와 - 기호
    @ 는 @
    [\w.] : 문자와 . 기호

import re

pattern = re.compile(r'[\w-]+@[\w.]+')
result = pattern.search('test@gmail.com hahahaha goood')
result2 = pattern.findall('test@gmail.com hahahaha goood')
if result:
    print(result.group())
    print(result2)

# 실행결과
'''
test@gmail.com
['test@gmail.com']
'''

 

※ 리스트에서 패턴에 해당되는 데이터를 찾아 출력하되, 람다 함수를 사용하여 출력할 수 있다. 

    https? : http 또는 https
    [\w.] : 문자와 숫자 그리고 . 기호
    \w+$ : 문자로 끝남
import re

webs = ['http://www.test.co.kr',            # 출력
        'https://www.test1.com',            # 출력
        'http://www.test.com',              # 출력
        'ftp://www.test.com',               # X
        'http:://www.test.com',             # X
       'htp://www.test.com',                # X
       'http://www.google.com',             # 출력
       'https://www.homepage.com.']         # X

pattern = re.compile(r'https?://[\w.]+\w+$')
result = list(map(lambda w:pattern.search(w), webs))
# print(result)

for url in result:
    # print(url.group())          # AttributeError: 'NoneType' 에러 발생
    if url:
        print(url.group())
        
# 실행결과
'''
[<re.Match object; span=(0, 21), match='http://www.test.co.kr'>, <re.Match object; span=(0, 21), match='https://www.test1.com'>, <re.Match object; span=(0, 19), match='http://www.test.com'>, None, None, None, <re.Match object; span=(0, 21), match='http://www.google.com'>, None]
http://www.test.co.kr
https://www.test1.com
http://www.test.com
http://www.google.com

'''

 


12. 파이썬 컴파일 - 연습문제 ( 파이썬에서의 유효성 검사 )

 

    이메일 주소의 적합성 체크
        kim@encore.com    : 올바른 이메일
        kim@encore          : 잘못된 이메일 ( . 이 없음)
        k!m@encore.com    : 잘못된 이메일 (특수문자 ! 안 됨)
        !km@encore.com    : 잘못된 이메일 (특수문자 ! 안 됨)

     [참고]
        ^[ ]  : 시작
        [^]   : not
        {2,9} : 최소 2개 최대 9개
        {2,}  : 최소 2개만 지정하고 최대는 지정하지 않음
        $     : 끝
import re

def email_check(email):
    pattern = re.compile('^[\w-]+@[\w]+\\.[\w]+$')   # (r'^[\w-]+@[\w]+\.[\w]+$') 과 동일
    result = pattern.search(email)
    if result:
        print('올바른 이메일')
    else:
        print('잘못된 이메일')

email_check('kim@encore.com')      
email_check('kim@encore')          
email_check('k!m@encore.com')      
email_check('!km@encore.com')       

# 실행결과
'''
올바른 이메일
잘못된 이메일
잘못된 이메일
잘못된 이메일
'''

 

# 참고용
pattern = re.compile(r'[^-=+,#/\?:^$.@*\"※~&%ㆍ!』\\‘|\(\)\[\]\<\>`\'…》][a-zA-Z0-9]+@[\w.]+com$')

 

 

    비밀번호 생성시 의 적합성 체크
    1. 비밀번호의 길이는 6-10
    2. 숫자와 알파벳으로만 구성되어야 함
    3. 대문자와 소문자가 섞여야 함 ( 대문자 1개 이상, 소문자 0개 이상)
    4. 위의 조건에 부합하면 잘못된 상황을 출력하고
       조건을 모두 만족하면 가능한 비밀번호임을 출력한다.
import re

def pwd_check(pwd):
    pattern = re.compile(r'[a-z]')
    result = pattern.search(pwd)
    if result:
        return result


pwd_check('abcdE')          # 길이오류
pwd_check('abcdef')         # 대문자 포함하지 않아 오류
pwd_check('Abcdef2')        # 성공
pwd_check('Abcdef_2')       # 특수문자 포함

 

 

 

 

 

 

반응형

'교육과정 > KOSMO' 카테고리의 다른 글

Day66  (0) 2021.01.15
Day65  (0) 2021.01.14
Day63  (0) 2021.01.12
Day62  (0) 2021.01.11
Day61  (0) 2021.01.08