파이썬(문자열, 파일 다루기)

LEEEEE·2021년 12월 29일
1

문자열 및 파일을 다뤄보자!


텍스트 데이터 문자열 저장

텍스트 데이터는 문자열(String)로 표현한다.
파이썬에서는 작은따옴표('), 큰따옴표(")로 묶어서 사용한다. 예제 코드는 아래와 같다.

1 my_str = 'Welcome!'
2 ur_str = "You're welcome."
3
4 print(my_str)
5 print(ur_str)

인코딩과 디코딩

문자열 데이터가 메모리에 저장될 때 컴퓨터 내부에서 0과 1로 변환되어 다뤄지게 된다. 이런 이진 데이터의 최소 단위는 비트(bit)이고, 비트가 8개 모이면 바이트(byte)가 된다. 이때 메모리에는 바이트로 저장이 된다.

개념 정리

  • 바이트(byte) : 컴퓨터의 기본 저장 단위
    • 1바이트(1byte)는 8비트(8bit)이다.
    • 1바이트에는 2의 8승 즉, 256개의 고유한 값을 저장할 수 있다.
  • 인코딩 (encoding) : 문자열을 바이트로 변환하는 과정
  • 디코딩 (decoding) : 바이트를 문자열로 변환하는 과정

텍스트 데이터의 처리 과정

텍스트 데이터는 문자열 데이터를 의미한다. 이런 문자열 데이터는 일종의 규약을 통해 인코딩이 진행된다. 이때 사용하는 표준 코드를 유니코드(Unicode)라고 한다.

좀 더 명확하게 공부하고 싶으면 아래의 링크 참조

파이썬에서도 내장함수인 ord()chr()을 이용해 유니코드를 확인할 수 있다.

  • ord() : 해당 문자에 대응하는 유니코드 숫자를 반환
  • chr() : 해당 유니코드 숫자에 대응하는 문자를 반환
1 print(ord('a'))    
2 print(ord('A'))
3 print(chr(97))
4 print(ord('가'))
5 print(chr(0xAC00)) 
/-------------------/
# 출력
97
65
a
44032

파이썬은 유니코드 규약에 따른다. 이로 인해 외부 데이터 및 데이터베이스로부터 데이터를 읽거나 보낼 때 인코딩 혹은 디코딩 과정을 거쳐야하고, 기본 설정되어있는 유니코드는 UTF-8이다.


문자열 다루기

1 s = 'I don't like Python!'
----------------------------
  File "/tmp/ipykernel_16/4145611764.py", line 1
    s = 'I don't like Python!'
               ^
SyntaxError: invalid syntax

위와 같이 문자열 내부에 작은따옴표(')나 큰따옴표("), 줄 바꿈등의 특수문자를 표현할 때 단순히 묶게되면 위의 코드와 같이 오류가 발생한다. 이런 오류를 방지할 수 있게 해주는 것이 바로 이스케이프 문자이다. 이스케이프 문자는 \[원하는 문자] 형태로 사용한다. 예제 코드는 아래와 같다.

1 #- 줄 바꿈
2 print("사회적\n거리두기")
3 print('--------------------------')
4
5 #- 탭(tab)
6 print("사회적\t거리두기")
7 print('--------------------------')
8
9 #- 작은따옴표 포함
10print('오늘부터 \'사회적 거리두기\'')
/-------------------------------------/
# 출력
사회적
거리두기
--------------------------
사회적	거리두기
--------------------------
오늘부터 '사회적 거리두기'

반대로 이스케이프 문자를 무시하고 싶을 때는 원시 문자열(raw string)을 사용한다. 문자열의 시작하는 따옴표 앞에 r을 붙여 사용이 가능하다.

1 print('Please don\'t touch it')
2 print(r'Please don\'t touch it')
/---------------------------------/
# 출력
Please don't touch it
Please don\'t touch it

내가 원하는 키워드로 시작하거 끝나는 데이터를 출력하고 싶을 때는 startswith('원하는 키워드'), endswith('원하는 키워드')를 사용할 수 있다.

1 EmployeeID = ['OB94382', 'OW34723', 'OB32308', 'OB83461', 'OB74830', 'OW37402', 'OW11235', 'OB82345'] 
Production_Employee = [P for P in EmployeeID if P.startswith('OB')]   # 'OB'로 시작하는 직원 ID를 다 찾는다.
Production_Employee
/------------------------------------------------------------------------------------------------------/
# 출력
['OB94382', 'OB32308', 'OB83461', 'OB74830', 'OB82345']
import os
image_dir_path = os.getenv("HOME") + "/data/pictures"   
# 각자의 사진이 보관된 디렉토리를 고르기
photo = os.listdir(image_dir_path )
png = [png for png in photo if png.endswith('.png')]
print(png)
/---------------------------------------------------/
# 출력
['image5.png', 'image2.png', 'image12.png', 'image3.png']

문자열에서 공백을 만들거나 없애는 방법이 있다.
우선 공백 생성에는 아래와 같은 방법이 있다.

  • 스페이스(space) : 한 칸 띄어쓰기
  • 탭(tab) \t : 네 칸 띄어쓰기. 때에 따라 두 칸 띄어쓰기로 표기되기도 한다.
  • 줄 바꿈(new line) : 줄 바꿈
  • 라인 피드 (line feed, 개행) \n : 줄 바꿈을 엄밀히 말하면 라인 피드라고 한다.
  • 캐리지 리턴 (carriage return, 복귀) \r : 커서를 맨 앞으로 이동시키는 것, 즉 커서를 원위치로 복귀(return)한다는 뜻이다. 커서를 맨 앞으로 보내고,\r 뒤에 문자가 있으면 그 문자를 출력한다.
1 print("사회적 거리두기")
2 print('--------------------------')
3 print("사회적\t거리두기")
4 print('--------------------------')
5 print("사회적\n거리두기")
6 print('--------------------------')
7 print("사회적\r거리두기")
/-----------------------------------/
# 출력
사회적 거리두기
--------------------------
사회적	거리두기
--------------------------
사회적
거리두기
--------------------------
거리두기

공백 제거에는 strip() 메서드를 사용해 처리한다.

1 txt = "      Strip white spaces.      "
2 print('[{}]'.format(txt))
3 print('--------------------------')
4
5 #- 양쪽 공백 제거 : strip()
6 print('[{}]'.format(txt.strip()))
7 print('--------------------------')
8
9 #- 왼쪽 공백 제거 : lstrip()
10 print('[{}]'.format(txt.lstrip()))
11 print('--------------------------')

12 #- 오른쪽 공백 제거 : rstrip()
13 print('[{}]'.format(txt.rstrip()))
/------------------------------------/
# 출력
[      Strip white spaces.      ]
--------------------------
[Strip white spaces.]
--------------------------
[Strip white spaces.      ]
--------------------------
[      Strip white spaces.]

대소문자 변환도 가능하다.

  • upper() : 모든 문자를 대문자로 변환
  • lower() : 모든 문자를 소문자로 변환
  • capitalize() : 첫 글자만 대문자로 변환
1 #- 모든 문자를 대문자로 변환 : upper()
2 txt = "I fell into AIFFEL"
3 txt.upper()
4
5 #- 모든 문자를 소문자로 변환 : lower()
6 txt.lower()
7
8 #- 첫 글자만 대문자로 변환 : capitalize()
9 txt.capitalize()
/--------------------------------------/
# 출력
'I FELL INTO AIFFEL'
'i fell into aiffel'
'I fell into aiffel'

문자열의 구성에 따라 boolean값을 반환할 수 있다.

  • isupper() : 문자열이 모두 대문자로만 되어 있으면 True, 그렇지 않으면 False를 반환
  • islower() : 문자열이 모두 소문자로만 되어 있으면 True, 그렇지 않으면 False를 반환
  • istitle() : 문자열의 첫 글자만 대문자로 되어 있으면 True, 그렇지 않으면 False를 반환
  • isalpha() : 문자열이 모두 알파벳 문자로만 되어 있으면 True, 그렇지 않으면 False를 반환
  • isalnum() : 문자열이 모두 알파벳 문자와 숫자로만 되어 있으면 True, 그렇지 않으면 False를 반환
  • isdecimal() : 문자열이 모두 숫자로만 되어 있으면 True, 그렇지 않으면 False를 반환
1 print("aiffel".isupper())
2 print("aiffel".islower())
3 print("PYTHON".istitle())
4 print("python101".isalpha())
5 print("python101".isalnum())
6 print("101".isdecimal())
/----------------------------/
# 출력
False
True
False
False
True
True

시퀀스 객체를 하나의 문자열로 합칠 수 있다. 반대로 문자열을 시퀀스 객체로 나눌 수 있다.

  • join() : tuple, list, string 등 반복 가능한(iterable) 객체를 받는 메서드, 각각의 원소를 모아 하나의 문자열로 합쳐 준다.
  • split() : 하나의 문자열을 구분자를 기준으로 나누어 준다.
1 stages = ['fundamentals', 'exploration', 'goingdeeper']
2 ",".join(stages)
3 'fundamentals,exploration,goingdeeper'.split(',')
/-------------------------------------------------------/
# 출력
'fundamentals,exploration,goingdeeper'
['fundamentals', 'exploration', 'goingdeeper']

문자열 내 문자열을 수정할 수 있다.

  • replace() : replace(s1, s2) 형태로 문자열 내 문자열 s1을 s2로 바꾼다.
1 sent = 'I can do it!'
2 sent.replace('I', 'You')
/------------------------/
# 출력
'You can do it!'

정규 표현식

거의 모든 운영 체제가 어떤 특정한 단어를 검색할 때 자주 사용하는 단어 검색 기능 Ctrl+F을 지원하고 있다. 이러한 기능이 바로 정규 표현식(regular expression, regex)에 근거해 만들어진 기능이다.

1 import re
2 sent = 'I can do it!'
3 pattern = re.sub("I", "You", sent)
4 pattern
/----------------------------------/
# 출력
'You can do it!'

정규 표현식은 특정 규칙을 가진 문자열의 집합을 표현하는 형식 언어로, 찾고자 하는 문자열 패턴을 정의하고 기존 문자열과 일치하는지를 비교하여 문자열을 검색하거나 다른 문자열로 치환하는 데 사용된다.

정규 표현식을 사용하기 위해서는 re모듈을 import해서 사용한다. 정규 표현식의 사용법은 크게 2단계로 나눠진다.

1) 찾고자 하는 문자열의 패턴을 정의한다.
2) 정의된 패턴과 매칭되는 경우를 찾아 다양한 처리를 한다.

이 중 1)의 과정을 컴파일(compile)이라고 한다.

1 #1단계 :  "the"라는 패턴을 컴파일한 후 패턴 객체를 리턴 
2 pattern = re.compile("the")    
3
4 # 2단계 : 컴파일된 패턴 객체를 활용하여 다른 텍스트에서 검색을 수행
5 pattern.findall('of the people, for the people, by the people')
/----------------------------------------------------------------/
# 출력
['the', 'the', 'the']

정규 표현식의 메서드

  • search() : 일치하는 패턴 찾기 (일치 패턴이 있으면 MatchObject를 반환)
  • match() : search()와 비슷하지만, 처음부터 패턴이 검색 대상과 일치해야 한다.
  • findall() : 일치하는 모든 패턴 찾기 (모든 일치 패턴을 리스트에 담아서 반환)
  • split() : 패턴으로 나누기
  • sub() : 일치하는 패턴으로 대체하기

match(), search() 등이 리턴하는 MatchObject의 메서드

  • group() : 실제 결과에 해당하는 문자열을 반환

패턴

  • [ ] : 문자
  • - : 범위
  • . : 하나의 문자
  • ? : 0회 또는 1회 반복
  • * : 0회 이상 반복
  • + : 1회 이상 반복
  • {m, n} : m ~ n
  • \d : 숫자, [0-9]와 동일
  • \D : 비 숫자, [^0-9]와 동일
  • \w : 알파벳 문자 + 숫자 + _, [a-zA-Z0-9_]와 동일
  • \W : 비 알파벳 문자 + 비숫자, [^a-zA-Z0-9_]와 동일
  • \s : 공백 문자, [ \t\n\r\f\v]와 동일
  • \S : 비 공백 문자, [^ \t\n\r\f\v]와 동일
  • \b : 단어 경계
  • \B : 비 단어 경계
  • \t : 가로 탭(tab)
  • \v : 세로 탭(vertical tab)
  • \f : 폼 피드
  • \n : 라인 피드(개행문자)
  • \r : 캐리지 리턴(원시 문자열)
#- 연도(숫자)
1 text = """
2 The first season of America Premiere League  was played in 1993. 
3 The second season was played in 1995 in South Africa. 
4 Last season was played in 2019 and won by Chennai Super Kings (CSK).
5 CSK won the title in 2000 and 2002 as well.
6 Mumbai Indians (MI) has also won the title 3 times in 2013, 2015 and 2017.
7 """
8 pattern = re.compile("[1-2]\d\d\d")
9 pattern.findall(text)
/--------------------------------------------------------------------------/
# 출력
['1993', '1995', '2019', '2000', '2002', '2013', '2015', '2017']
1 #- 전화번호(숫자, 기호)
2 phonenumber = re.compile(r'\d{3}-\d{3}-\d{4}')
3 phone = phonenumber.search('This is my phone number 010-111-1111')
4 if phone:
5	print(phone.group())
6 print('------')
7 phone = phonenumber.match ('This is my phone number 010-111-1111')
8 if phone:
9	print(phone.group())
/------------------------------------------------------------------/
# 출력
010-111-1111
------
1 #- 이메일(알파벳, 숫자, 기호)
2 text = "My e-mail adress is doingharu@aiffel.com, and tomorrow@aiffel.com"
3 pattern = re.compile("[0-9a-zA-Z]+@[0-9a-z]+\.[0-9a-z]+")
4 pattern.findall(text)
/--------------------------------------------------------------------------/
# 출력
['doingharu@aiffel.com', 'tomorrow@aiffel.com']

파일과 디렉터리

지금까지는 문자열 데이터를 메모리에 저장했다. 이는 데이터의 로드 및 액세스 속도가 빠르다는 장점이 있지만, 전원이 공급이 안되면 데이터가 날라간다는 단점이 있다.

파일

데이터를 날리지 않기 위해 우리는 파일을 만들어 데이터를 저장한다. 파이썬에서 파일을 수정, 저장하기 위해서는 write를 사용하여 작업한다.

1 f = open("hello.txt","w") 
2 #- open(파일명, 파일모드)
3 #- 파일을 열고 파일 객체를 반환 
4 for i in range(10):
5    f.write("안녕")
6    #- write() 메서드로 '안녕'을 10번 쓴다.
7 f.close()
8 #- 작업이 끝나면 close() 메서드로 닫는다. *필수!
9 print("완료!")
/-------------------------------------------/
# 출력
완료!

반대로 저장된 파일을 읽기위해서는 read를 사용한다.

1 with open("hello.txt", "r") as f:
2	print(f.read())
/---------------------------------/
# 출력
안녕안녕안녕안녕안녕안녕안녕안녕안녕안녕
안녕하세요.
반갑습니다.
오랫만입니다.

파일 관련 메서드

  • f.read() : 파일을 읽는다.
  • f.readline() : 파일을 한 줄씩 읽는다.
  • f.readlines() : 파일 안의 모든 줄을 읽어 그 값을 리스트로 반환한다.
  • f.write(str) : 파일에 쓴다. 문자열 타입을 인자로 받는다.
  • f.writelines(str) : 파일에 인자를 한 줄씩 쓴다.
  • f.close() : 파일을 닫는다.
  • f.seek(offset) : 해당 파일의 위치(offset)를 찾아 파일의 커서를 옮긴다. 파일의 처음 위치는 0이다.
  • f.tell() : f.tell(): 현재 커서의 위치를 반환한다.

디렉터리

파일이 저장된 위치를 디렉터리라고 한다. 파일을 정상적으로 읽기 위해서는 어느 디렉터리에 위치하는지가 중요하다.
최상위 디렉터리를 루트 디렉터리(root directory)라고 한다.

  • Window 운영 체제 : C:\
  • Linux 계열 운영 체제 : /

리눅스의 파일 시스템


모듈과 패키지

파이썬에서 지원하는 디렉터리 관련 표준 라이브러리

  • sys
  • os
  • glob

각 모듈은 import해서 사용하면 된다.
파이썬의 실행파일(python.exe) 위치를 알아보자!

1 import sys
2 sys.executable
/--------------/
# 출력
'/opt/conda/bin/python'

임포트할 때 불러오는 모듈들이 위치한 경로 출력

1 sys.path
/---------/
# 출력
['/aiffel',
 '/aiffel/storage/package',
 '/opt/conda/lib/python39.zip',
 '/opt/conda/lib/python3.9',
 '/opt/conda/lib/python3.9/lib-dynload',
 '',
 '/opt/conda/lib/python3.9/site-packages',
 '/opt/conda/lib/python3.9/site-packages/IPython/extensions',
 '/aiffel/.ipython']

모듈과 패키지 개념 및 함수

개념

  • 모듈(module) : 파이썬으로 만든 코드가 들어간 파일 .py
  • 패키지(package) : 능적으로 동일하거나 동일한 결과를 만드는 모듈들의 집합 또는 폴더. 종종 라이브러리라고도 불림
  • 라이브러리(library) : 모듈과 패키지의 집합. 패키지보다 포괄적인 개념이나 패키지와 혼용되어 사용되기도 함.
  • PIP(Package Installer for Python) : 패키지 관리자로 파이썬을 설치하면 기본으로 설치됨
  • PyPA(Python Packaging Authority) : 파이선 패키지를 관리하고 유지하는 그룹
  • PyPI(The Python Package Index) : 파이썬 패키지들의 저장소

함수

  • sys.path : 현재 폴더와 파이썬 모듈들이 저장되는 위치를 리스트 형태로 반환
  • sys.path.append() : 자신이 만든 모듈의 경로를 append 함수를 이용해서 추가함. 그 후 추가한 디렉터리에 있는 파이썬 모듈을 불러와 사용할 수 있다.
  • os.chdir() : 디렉터리 위치 변경
  • os.getcwd() : 현재 자신의 디렉터리 위치를 반환
  • os.mkdir() : 디렉터리 생성
  • os.rmdir() : 디렉터리 삭제 (단, 디렉터리가 비어 있을 경우)
  • glob.glob() : 해당 경로 안의 디렉터리나 파일들을 리스트 형태로 반환
  • os.path.join() : 경로(path)를 병합하여 새 경로 생성
  • os.listdir() : 디렉터리 안의 파일 및 서브 디렉터리를 리스트 형태로 반환
  • os.path.exists() : 파일 혹은 디렉터리의 경로 존재 여부 확인
  • os.path.isfile() : 파일 경로의 존재 여부 확인
  • os.path.isdir() : 디렉터리 경로의 존재 여부 확인
  • os.path.getsize() : 파일의 크기 확인

CSV 파일

CSV는 Comma Seperated Value의 약자로, 쉼표로 구분된 파일을 말한다. 판다스(pandas)의 DataFrame은 to_csv 메서드를 지원한다.

직접 CSV 파일을 만들어보자!
1) 데이터 준비

1 #- 1. 데이터를 준비합니다.
2 fields = ["title", "singer", "released date"]
3 rows = [ ["Tho Box","Roddy Ricch","2019-12-19"],
4               ["Don't Start Now", "Dua Lipa", "2019-11-01"],
5               ["Life Is Good", "Future Featuring Drake", "2020-02-10"],
6               ["Blinding", "The Weeknd", "2019-11-29"],
7               ["Circles", "Post Malone","2019-08-30"]]
8
9 print("슝~")
/-----------------------------------------------------------------------/
# 출력~

2) 판다스 사용

1 #- 2. 판다스를 이용해 데이터를 csv 파일로 저장합니다.
2 import pandas as pd
3
4 df=pd.DataFrame(rows, columns=fields)
5 df.to_csv('pandas.csv',index=False)
6
7 print("슝~")
/----------------------------------------------/
# 출력~

3) 파일 확인하기

1 df = pd.read_csv('pandas.csv')
2 df.head()
# 출력
title	singer	released date
0	Tho Box	Roddy Ricch	2019-12-19
1	Don't Start Now	Dua Lipa	2019-11-01
2	Life Is Good	Future Featuring Drake	2020-02-10
3	Blinding	The Weeknd	2019-11-29
4	Circles	Post Malone	2019-08-30

XML 파일

XML은 Extensible Markup Language의 약자로, 다목적 마크업 언어이다. HTML과 유사한 형태이다.
아래는 간단한 xml 파일이다.

<Person>
    <Name>김이박</Name>
    <Age>28</Age>
    <Place>강남</Place>
</Person>

XML은 태그를 사용하여 구성한다. 태그는 <글자>의 형태를 이루고 있다. 기본적으로 <태그> 내용 </태그>의 형태를 이루지만, 태그 안에 속성(attribute)값이 포함될 수 있다.

<table>
  <row>
    <cell>
      <Data ss:Type="String">Notice</Data>
    </cell>
  </row>

XML 파일 만들기

파이썬 표준 라이브러리인 ElementTree를 사용한다.

  • Element() : 태그 생성
  • SubElement() : 자식 태그 생성
  • tag : 태그 이름
  • text : 텍스트 내용 생성
  • attrib : 속성 생성

생성된 XML 구조를 저장할 때 dump()를 사용한다.

  • write() : XML 파일로 저장
  • 리스트(list)와 유사한 메서드를 제공
    • append(), insert(), remove(), pop()
1 import xml.etree.ElementTree as ET
2
3 person = ET.Element("Person")
4 name = ET.Element("name")
5 name.text = "김이박"
6 person.append(name)
7
8 age = ET.Element("age")
9 age.text = "28"
10 person.append(age)
11
12 ET.SubElement(person, 'place').text = '강남'
13
14 ET.dump(person)

아래와 같은 XML이 생성된다.

<Person>
	<name>김이박</name>
	<age>28</age>
	<place>강남</place>
</Person>

JSON 파일

JSON은 JavaScript Object Notation의 약자로, 웹 언어인 JavaScript의 데이터 객체 표현 방식이다. 웹 브라우저와 다른 애플리케이션 사이에서 HTTP 요청으로 데이터를 보낼 때 널리 사용하는 표준 파일 포맷 중 하나로, XML과 더불어 웹 API나 config 데이터를 전송할 때 많이 쓰인다. 아래는 간단한 예시이다.

person = {
      "first name" : "Yuna",
      "last name" : "Jung",
      "age" : 33,
      "nationality" : "South Korea",
      "education" : [{"degree":"B.S degree", "university":"Daehan university", "major": "mechanical engineering", "graduated year":2010}]
       } 

파이썬의 딕셔너리와 유사한 구조를 갖고 있으며, CSV 파일에 비해 좀 더 유연하게 데이터를 표현할 수 있고 XML 파일보다 파일을 쉽게 읽고 쓸 수 있다는 장점이 있다.

JSON 파싱

1) JSON 파일 저장
파이썬 dictionary 타입은 JSON으로 저장할 수 있다.
위 예시로 보인 person이라는 dict 객체를 JSON 파일로 저장해 보자!

1 import json
2
3 person = {
4      "first name" : "Yuna",
5      "last name" : "Jung",
6      "age" : 33,
7      "nationality" : "South Korea",
8      "education" : [{"degree":"B.S degree", "university":"Daehan university", "major": "mechanical engineering", "graduated year":2010}]
9       }
10
11 with open("person.json", "w") as f:
12    json.dump(person , f)
13
14 print("슝~")

2) JSON 파일 읽기
반대로 JSON 파일의 내용을 파이썬 dict 객체로 읽을 수 있다.

1 import json
2
3 with open("person.json", "r", encoding="utf-8") as f:
4    contents = json.load(f)
5    print(contents["first name"])
6    print(contents["education"])
/-----------------------------------------------------/
# 출력
Yuna
[{'degree': 'B.S degree', 'university': 'Daehan university', 'major': 'mechanical engineering', 'graduated year': 2010}]

1개의 댓글

comment-user-thumbnail
2021년 12월 29일

정리 잘 보고 갑니다!

답글 달기