day 5 파이썬으로 문자열, 파일 다루기

8 minute read

파이썬으로 코딩 시작하기

  • 텍스트 데이터를 문자열로 저장한다는 것

    인코딩과 디코딩

    문자열 다루기

    정규 표현식

  • 파일과 디렉토리

    파일

    디렉토리

    모듈과 패키지

  • 여러가지 파일 포맷 다루기

    CSV 파일

    XML파일

    JSON 파일

문자열 다루기

이스케이프 문자

image

greeting = '안녕하세요?'
print(greeting)
greeting = '안녕!'
안녕하세요?

코드는 한 줄씩 순서대로 실행되기 때문에, print() 함수가 불리는 시점의 greeting 변수의 값인 안녕하세요?가 출력됩니다.

def say_hi_nice():
    print('안녕!')
    print('반가워.')
#- 새로운 함수를 정의합니다.
say_hi_nice()
#- 함수를 호출합니다.
..
..
안녕!
반가워.

startswith, endswith

  • startswith
    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']
    
  • endswith
>>> import os
>>> photo = os.listdir('/Users/jooyoungson/Documents/photo')
>>> png = [png for png in photo if png.endswith('.png')]
>>> print(png)
metaflow.png
Pytorch.png
smartphone.png
TDG.png

공백 문자 처리 : trimming

컴퓨터의 스페이스바(space bar)처럼 일상에서 자주 쓰고 접하는 띄어쓰기! 지금부터 살펴 볼 공백 문자는 이 띄어쓰기로 표기되는 항목인데요. 문자열 작업에서는 다듬기 즉, trimming이라고 불립니다.

여러가지 공백 문자

  • 스페이스(space) : 한 칸 띄어쓰기
  • 탭(tab) \t : 네 칸 띄어쓰기. 경우에 따라 두 칸 띄어쓰기로 표기되기도 합니다.
  • 줄 바꿈(new line) : 줄 바꿈
  • 라인 피드 (line feed) \n : 줄 바꿈을 엄밀히 말하면 라인 피드라고 합니다.
  • 개행 복귀 (carriage return) \r : 커서를 맨 앞으로 이동시키는 것, 즉 커서를 원위치로 복귀(return)한다는 뜻입니다.
print("사회적 거리두기")
print('--------------------------')
print("사회적\t거리두기")
print('--------------------------')
print("사회적\n거리두기")
print('--------------------------')
print("사회적\r거리두기")
..
..

사회적 거리두기
--------------------------
사회적	거리두기
--------------------------
사회적
거리두기
--------------------------
거리두기
  • 공백 문자 제거하기
#txt = "      공백 문자를 제거해 보아요.      "
txt = "      Strip white spaces.      "
print('[{}]'.format(txt))
print('--------------------------')

#- 양쪽 공백 제거 : strip()
print('[{}]'.format(txt.strip()))
print('--------------------------')

#- 왼쪽 공백 제거 : lstrip()
print('[{}]'.format(txt.lstrip()))
print('--------------------------')

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

대소문자 관련

  • upper() : 모든 문자를 대문자로 변환합니다.

  • lower() : 모든 문자를 소문자로 변환합니다.

  • capitalize() : 첫 글자만 대문자로 변환합니다.

isX

  • isupper() : 문자열이 모두 대문자로만 되어 있으면 True, 그렇지 않으면 False를 반환

  • islower() : 문자열이 모두 소문자로만 되어 있으면 True, 그렇지 않으면 False를 반환

  • istitle(): 문자열의 첫 글자만 대문자로 되어 있으면 True, 그렇지 않으면 False를 반환

  • isalpha(): 문자열이 모두 알파벳 문자로만 되어 있으면 True, 그렇지 않으면 False를 반환

  • isalnum(): 문자열이 모두 알파벳 문자와 숫자로만 되어 있으면 True, 그렇지 않으면 False를 반환

  • isdecimal(): 문자열이 모두 숫자로만 되어 있으면 True, 그렇지 않으면 False를 반환

join()과 split()

#- split()
'fundamentals,exploration,goingdeeper'.split(',')
..
..
['fundamentals', 'exploration', 'goingdeeper']

replace()

sent = 'I can do it!'
sent.replace('I', 'You')
..
..
'You can do it!'

불변(immutable)의 문자열

가변객체(mutable object)

  • 객체를 생성한 후 객체의 값을 수정할 수 있습니다.

  • 변수는 값이 수정된 같은 객체를 가리키게 됩니다.

  • e.g. list, set, dict

불변객체(immutable object)

  • 객체를 생성한 후 객체의 값을 수정할 수 없습니다.

  • 변수는 해당 값을 가진 다른 객체를 가리키게 됩니다.

  • e.g. int, float, complex, bool, string, tuple, frozen set

ID

sent = 'I fell into AIFFEL'
print(sent)
print(id(sent))
sent.upper()
print(sent)
print(id(sent))
..
..
I fell into AIFFEL
140029428355520
I fell into AIFFEL
140029428355520

정규 표현식

import re
sent = 'I can do it!'
pattern = re.sub("I", "You", sent)
pattern
..
..
'You can do it!'


#1단계 :  "the"라는 패턴을 컴파일한 후 패턴 객체를 리턴합니다. 
pattern = re.compile("the")    

# 2단계 : 컴파일된 패턴 객체를 활용하여 다른 텍스트에서 검색을 수행합니다.
pattern.findall('of the people, for the people, by the people')
..
..
['the', 'the', 'the']

re.findall('the', 'of the people, for the people, by the people')
..
..
['the', 'the', 'the']

메소드

  • search() : 일치하는 패턴 찾기 (일치 패턴이 있으면 MatchObject를 반환합니다)

  • match() : search()와 비슷하지만, 패턴이 검색대상에 처음부터 일치해야 합니다.

  • findall() : 일치하는 모든 패턴 찾기 (모든 일치 패턴을 리스트에 담아서 반환합니다)

  • split() : 패턴으로 나누기

  • sub() : 일치하는 패턴으로 대체하기

아래는 search(), match() 등이 리턴하는 MatchObject가 가진 메소드입니다.

  • group() : 실제 결과에 해당하는 문자열을 반환합니다.
src = "My name is..."
regex = re.match("My", src)
print(regex)
if regex:
    print(regex.group())
else:
    print("No!")
..
..
<re.Match object; span=(0, 2), match='My'>
My

패턴 : 특수문자, 메타문자

패턴이야말로 정규 표현식을 강력하게 해주는 도구 인데요. 특수문자 혹은 메타문자라 불리는 []. -. . ? * + {} / 등을 이용해 특수한 패턴을 만들 수 있습니다. 자, 어떤 것들이 있는지 볼까요?

[ ] : 문자
- : 범위
. : 하나의 문자
? : 0회 또는 1회 반복
* : 0회 이상 반복
+ : 1회 이상 반복
{m, n} : m ~ n
\d : 숫자
\D : 비숫자
\w : 알파벳 문자
\W : 비알파벳 문자
\s : 공백 문자
\S : 비공백 문자
\b : 단어 경계
\B : 비 단어 경계
#- 연도(숫자)
text = """
The first season of America Premiere League  was played in 1993. 
The second season was played in 1995 in South Africa. 
Last season was played in 2019 and won by Chennai Super Kings (CSK).
CSK won the title in 2000 and 2002 as well.
Mumbai Indians (MI) has also won the title 3 times in 2013, 2015 and 2017.
"""
pattern = re.compile("[1-2]\d\d\d")
pattern.findall(text)
..
..
['1993', '1995', '2019', '2000', '2002', '2013', '2015', '2017']

#- 전화번호(숫자, 기호)
phonenumber = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
phone = phonenumber.search('This is my phone number 010-111-1111')
if phone:
  print(phone.group())
print('------')
phone = phonenumber.match ('This is my phone number 010-111-1111')
if phone:
  print(phone.group())
..
..
010-111-1111
------

#- 이메일(알파벳, 숫자, 기호)
text = "My e-mail adress is doingharu@aiffel.com, and tomorrow@aiffel.com"
pattern = re.compile("[0-9a-zA-Z]+@[0-9a-z]+\.[0-9a-z]+")
pattern.findall(text)
..
..
['doingharu@aiffel.com', 'tomorrow@aiffel.com']

구현 순서

  • import re 를 통해 정규식 모듈을 가져옵니다.

  • re.compile() 함수로 Regex 객체를 만듭니다.

  • 검색할 문자열을 Regex 객체의 search() , findall() 메소드로 전달합니다.

파일 다루기

파일 관련 메소드

  • f.read() : 파일을 읽는다.

  • f.readline() : 파일을 한 줄씩 읽는다.

  • f.readlines() : 파일 안의 모든 줄을 읽어 그 값을 리스트로 반환한다.

  • f.write(str) : 파일에 쓴다. 문자열 타입을 인자로 받는다.

  • f.writelines(str) : 파일에 인자를 한 줄씩 쓴다.

  • f.close() : 파일을 닫는다.

  • f.seek(offset) : 새 파일의 위치를 찾는다.

디렉토리 다루기

저장한 파일명이 project.txt이고 그 경로가 C:\Users\person\Documents라고 해봅시다. C 드라이브 에 있는 Users 폴더에 속한 person 폴더에 있는 Documents 폴더에 project.txt라는 파일이 저장되어 있다는 뜻이지요.

  • Window 운영 체제 : C:\

  • Linux 계열 운영 체제 : /

모듈과 패키지

파이썬에서는 지원하는 디렉토리 관련 표준 라이브러리는 다음과 같습니다.

  • sys

  • os

  • glob

#- 현재 실행되고 있는 파이썬 실행 파일의 디렉토리를 반환합니다.
import sys
sys.executable
..
..
'/opt/conda/bin/python'


#- 임포트할 때 불러 오는 모듈들이 위치한 경로입니다.
sys.path

['/aiffel',
 '/aiffel/storage/package',
 '/opt/conda/lib/python37.zip',
 '/opt/conda/lib/python3.7',
 '/opt/conda/lib/python3.7/lib-dynload',
 '',
 '/opt/conda/lib/python3.7/site-packages',
 '/opt/conda/lib/python3.7/site-packages/IPython/extensions',
 '/aiffel/.ipython']

개념

  • 모듈(module) : 파이썬으로 만든 코드가 들어간 파일 .py

  • 패키지(package) : init.py가 포함된 폴더로 흔히 라이브러리라고 칭함

  • 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 파일

#- 1. 데이터를 준비합니다.
fields = ["title", "singer", "released date"]
rows = [ ["Tho Box","Roddy Ricch","2019-12-19"],
               ["Don't Start Now", "Dua Lipa", "2019-11-01"],
               ["Life Is Good", "Future Featuring Drake", "2020-02-10"],
               ["Blinding", "The Weeknd", "2019-11-29"],
               ["Circles", "Post Malone","2019-08-30"]]

#- 2. 판다스를 이용해 데이터를 csv 파일로 저장합니다.
import pandas as pd

df=pd.DataFrame(rows, columns=fields)
df.to_csv('pandas.csv',index=False)

filename = "test.csv"
with open(filename, 'w+', newline='\n') as csv_file: 
    csv_writer = csv.writer(csv_file) 
    csv_writer.writerow(fields) 
    csv_writer.writerows(rows)

#- test.csv 파일을 직접 열어서 눈으로 살펴 보세요. -#

image


df = pd.read_csv('pandas.csv')
df.head()

image

XML 파일

  • XML

XML은 Extensible Markup Language의 약자로, 다목적 마크업 언어입니다.

<Person>
    <Name>이펠</Name>
    <Age>28</Age>
    <Place>강남</Place>
</Person>

#- 꺽쇠 괄호 안에 태그 이름을 정의하고, 태그 사이에 데이터를 기록하는 형식입니다.
#- 참고로, 태그 이름은 사용자가 마음대로 지정할 수 있습니다.
  • WHO athena API GHO
<?xml version="1.0" encoding="utf-8"?>
#- XML의 버전과 인코딩을 명시하는 태그입니다. *필수!
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:o="urn:schemas-microsoft-com:office"
          xmlns:x="urn:schemas-microsoft-com:excel"
          xmlns:ss="urn:schemas-microsoft-com:spreadsheet"
          xmlns:html="http://www.w3.org/TR/REC-html40">
   <DocumentProperties/>
   <Styles>
      <Style ss:ID="Hyperlink" ss:Name="Hyperlink">
         <Font ss:Color="#0000FF" ss:Underline="Single"/>
      </Style>
      <Style ss:ID="header">
         <Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
         <NumberFormat ss:Format="@"/>
      </Style>
   </Styles>
   <Worksheet ss:Name="notice">
      <Table>
         <Row>
            <Cell>
               <Data ss:Type="String">Notice</Data>
            </Cell>
         </Row>
         <Row/>
         <Row>
            <Cell>
               <Data ss:Type="String">Date generated</Data>
            </Cell>
         </Row>

XML 파일을 훑어보니 꺽쇠(<글자>) 부분을 태그(tag)라고 부르는데요. 위 파일에는 , 등의 태그들로 구성되어 있음을 확인할 수 있습니다. 태그는 기본적으로 <태그> 내용 형태로 구성되어 있지만 아래의 오른쪽 그림처럼 태그에 속성(attribute)값이 포함될 수도 있습니다.

  • XML은 다목적 마크업 언어(Extensible Markup Language)이다.

  • 마크업 언어는 태그(tag)로 이루어진 언어를 말하며, 상위(부모)태그 - 하위(자식)태그의 계층적 구조를 가지고 있다.

  • XML은 요소(element)들로 이루어져 있다.

  • 요소는 <열린태그> 내용 </닫힌태그>가 기본적인 구조이며, 속성(attribute)값을 가질 수도 있다.

ElementTree

파이썬 표준 라이브러리인 ElementTree는 XML 관련 기능을 다음과 같이 제공합니다.

  • Element() : 태그 생성

  • SubElement() : 자식 태그 생성

  • tag : 태그 이름

  • text : 텍스트 내용 생성

  • attrib : 속성 생성

dump()

생성된 XML 요소 구조를 시스템(sys.stdout)에 사용합니다.

  • write() : XML 파일로 저장

  • 리스트(list)와 유사한 메소드를 제공

  • append, insert, remove, pop

import xml.etree.ElementTree as ET

person = ET.Element("Person")
name = ET.Element("name")
name.text = "이펠"
person.append(name)

age = ET.Element("age")
age.text = "28"
person.append(age)

ET.SubElement(person, 'place').text = '강남'

ET.dump(person)
..
..
<Person>
<name>이펠</name>
<age>28</age>
<place>강남</place>
</Person>

person.attrib["id"] = "0x0001"
name.tag = "firstname"
ET.dump(person)
..
..
<Person id="0x0001">
<firstname>이펠</firstname>
<age>28</age>
<place>강남</place>
</Person>

lastname = ET.Element('lastname', date='2020-03-20')
lastname.text = '아'
person.insert(1,lastname)
ET.dump(person)
..
..
<Person id="0x0001">
<firstname>이펠</firstname>
<lastname date='2020-03-20'>아</lastname>
<age>28</age>
<place>강남</place>
</Person>

XML 파싱하기

pip list | grep beautifulsoup4
pip list | grep lxml

JSON

import json

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}]
       } 

with open("person.json", "w") as f:
    json.dump(person , f)

with open("person.json", "r", encoding="utf-8") as f:
    contents = json.load(f)
    print(contents["first name"])
    print(contents["education"])
..
..
Yuna
[{'degree': 'B.S degree', 'university': 'Daehan university', 'major': 'mechanical engineering', 'graduated year': 2010}]

Leave a comment