파알못 파이썬: 6. 파이썬 표준 라이브러리

Table of Content

파이썬을 공부한 내용을 정리한 글입니다. 파알못이라 이상하거나 틀린 내용이 있을 수 있습니다…

경로(Path) 작업

파일 또는 디렉토리 관련 작업 시에 경로(Path) 객체를 사용합니다. 경로 객체를 사용하기 위해 pathlib 모듈을 가져옵니다.

from pathlib import Path

윈도우와 맥 그리고 리눅스에서 경로 선언은 다음과 같이 합니다.

# Windows
path = Path("C:\\Program Files\\Microsoft")
path = Path(r"C:\Program Files\Microsoft")

# MacOS 또는 Linux
path = Path("/usr/local/bin")
path = Path("ecoomerce/__init__.py")  # 현재폴더/파일명

경로도 결합 연산이 가능합니다.

path = path = Path() / "ecommerce" / "__init__.py"

경로의 주요 연산은 다음과 같습니다.

# 홈 디렉토리
path = Path.home()  # 홈 디렉토리
path = Path("ecommerce/__init__.py")  # 현재 폴더

print(path.name)  # 이 경로의 파일 이름(확장자 포함)
print(path.stem)  # 이 경로의 파일 이름(확장자 미포함)
print(path.suffix)  # 이 경로의 파일 확장자
print(path.parent)  # 부모 디렉토리

print(path.absolute())  # 절대 경로
print(path.exists()) # 파일 존재 여부
print(path.is_file()) # 파일 여부
print(path.is_dir()) # 디렉토리 여부

path = path.with_name("test.txt") # 이름을 변경한 경로 반환
path = path.with_suffix(".py") # 확장자를 변경한 경로 반환
print(path)

디렉토리(Directories) 작업

from pathlib import Path

path = Path("ecommerce")

# 경로 내 파일 및 디렉토리를 포함하는 제너레이터(Generator) 반환
for p in path.iterdir():
    print(p)

# 경로 내 파일 및 디렉토리를 포함하는 리스트(List) 생성
paths = [p for p in path.iterdir()]
print(paths)

# 경로 내 디렉토리를 포함하는 리스트(List) 생성
paths = [p for p in path.iterdir() if p.is_dir()]
print(paths)

# 경로 내 조건에 맞는 파일을 포함하는 제너레이터(Generator) 반환
for p in path.glob("*.py"):
    print(p)

# 경로 내 조건에 맞는 모든 파일을 포함하는 리스트(List) 생성
py_files = [p for p in path.rglob("*.py")]
print(py_files)

파일(Files) 작업

경로 객체를 사용하여 파일의 위치를 지정한 후 파일을 제어할 수 있습니다.

from pathlib import Path

path = Path("ecommerce/__init__.py")

print(path.exists())  # 파일 존재여부
path.rename("ecommerce/init.txt")  # 파일 이름 변경
path.unlink()  # 파일 삭제

파일의 크기, 생성 및 변경 시간 등을 확인하려면 stat() 함수를 사용합니다.

from pathlib import Path

path = Path("ecommerce/__init__.py")
print(path.stat())  # 파일 상태 정보 

위의 방법으로 파일 상태 정보를 확인하면 파일 생성 및 변경 시간이 정수로 표시됩니다. 사람이 알아볼 수 있도록 표시하려면 ctime() 함수를 사용합니다.

from pathlib import Path
from time import ctime

path = Path("ecommerce/__init__.py")
print(ctime(path.stat().st_ctime))  # 파일 생성 시간을 사람이 알아볼 수 있도록 출력

파일을 읽어올 때는 write_bytes() 또는 write_text() 함수를 사용합니다.

from pathlib import Path

path = Path("ecommerce/__init__.py")
print(path.read_bytes())  # 파일을 읽어 이진(binary) 데이터로 출력
print(path.read_text())  # 파일을 읽어 텍스트로 출력

파일에 데이터를 쓸 때는 write_bytes() 또는 write_text 함수를 사용합니다.

from pathlib import Path

path = Path("ecommerce/test.txt")
path.write_text("안녕요?ㅎ")
path.write_bytes(b"hello?")

파일을 복사하는 코드는 다음과 같이 작성할 수 있겠지만

from pathlib import Path

source = Path("ecommerce/__init__.py")
target = Path() / "__init__.py"
target.write_text(source.read_text())

이보다 shutil(셸 유틸리티)를 사용하면 편리하게 코드를 작성할 수 있습니다.

from pathlib import Path
import shutil

source = Path("ecommerce/__init__.py")
target = Path() / "__init__.py"
shutil.copy(source, target)  # shutil

zip 파일 작업

파이썬에서 zip 파일을 작업하기 위해서 zipfile 모듈을 사용합니다.

아래 코드는 경로 객체에 지정된 디렉토리 내 모든 파일을 압축하는 코드입니다.

from pathlib import Path
from zipfile import ZipFile

with ZipFile("files.zip", "w") as zip: # 쓰기(w) 모드 ZipFile 객체 생성
    for path in Path("ecommerce").rglob("*.*"):  # ecommerce 디렉토리 내 모든 파일 경로를 꺼내옴
        zip.write(path)

아래 코드는 압축파일 정보를 조회하거나 압축을 푸는 코드입니다.

from pathlib import Path
from zipfile import ZipFile

with ZipFile("files.zip") as zip:  # 읽기모드 ZipFile 객체 생성
    print(zip.namelist())

    info = zip.getinfo("ecommerce/__init__.py")  # 해당 파일에 대한 정보 객체 생성
    print(info.file_size)  # 압축 전 파일 사이즈
    print(info.compress_size)  # 압축 후 파일 사이즈

    zip.extractall("extract")  # 해당 폴더에 zip 압축파일 풀기

csv 파일 작업

값을 쉼표(,) 단위로 구분하는 csv 파일을 파이썬에서 작업하려면 csv 모듈을 사용합니다.

아래 코드는 csv 파일을 생성하는 코드입니다.

import csv

with open("data.csv", "w") as file:  # 쓰기(w)모드 파일 객체 생성
    writer = csv.writer(file)
    writer.writerow(["transaction_id", "product_id", "price"])  # 제목 찍기
    writer.writerow([1000, 1, 5])  # 값 찍기
    writer.writerow([1000, 2, 5])

아래 코드는 csv 파일을 읽어오는 코드입니다.

import csv

with open("data.csv") as file:  # 읽기모드 파일 객체 생성
    reader = csv.reader(file)
    print(list(reader))

아래 코드는 csv 파일 내용을 한 행씩 꺼내 읽어오는 코드입니다.

import csv

with open("data.csv") as file:  # 읽기모드 파일 객체 생성
    reader = csv.reader(file)

    for row in reader:  # 한 행씩 읽어오기
        print(row)

JSON 파일 작업

파이썬에서 JSON 파일 작업을 위해 json 모듈을 사용합니다.

파이썬의 Dictionary 객체 구조는 JSON과 매우 비슷하지만 약간 다릅니다. 따라서 json 모듈의 dumps() 함수를 사용하면 Dictionary 객체를 JSON 데이터로 변환할 수 있습니다.

import json
from pathlib import Path

# Dictionary 생성
movies = [
    {"id": 1, "title": "Weathering with you", "year": 2019},
    {"id": 2, "title": "Your Name.", "year": 2017},
]

# Dictionary -> JSON 변환
data = json.dumps(movies)

# JSON 파일 저장
Path("movies.json").write_text(data)

JSON 데이터를 불러올 땐 json 모듈의 loads() 함수를 사용합니다.

import json
from pathlib import Path

# JSON 파일 읽어오기
data = Path("movies.json").read_text()
movies = json.loads(data)
print(movies)
print(movies[0]["title"])  # 첫 번째 데이터의 title 속성 값 출력

SQLite 작업

SQLite는 애플리케이션에서 데이터를 저장하는 데 사용하는 매우 가벼운 데이터베이스입니다.

import sqlite3
import json
from pathlib import Path

# JSON 파일 불러오기
movies = json.loads(Path("movies.json").read_text())
print(movies)

# SQLite 연결 객체 생성: 매개변수는 데이터베이스 파일 명
with sqlite3.connect("db.sqlite3") as conn:
    command = "INSERT INTO Movies VALUES(?, ?, ?)"  # ?는 execute() 함수에서 지정해줄 값

    for movie in movies:
        conn.execute(command, tuple(movie.values()))

    conn.commit()

위의 코드는 에러가 발생합니다. Movies 테이블에 데이터를 삽입하려 하지만 Movies 테이블이 존재하지 않기 때문입니다.

https://sqlitebrowser.org/dl 에서 DB Browser for SQLite를 다운받아 설치 후 실행하여 파이썬에 의해 생성된 db.sqlite3 파일을 엽니다. 그 다음 테이블 생성하기를 클릭하여 테이블을 생성합니다. 여기서 테이블 이름은 Movies, 필드는 Id(INTEGER, PK(Primary Key, 기본 키)), Title(TEXT), Year(INTEGER)로 설정하여 만들겠습니다. 테이블을 생성한 후 변경사항 저장하기(W)를 클릭하여 저장합니다.

이제 위에서 에러가 발생했던 코드를 실행하면 에러가 발생하지 않습니다. 코드를 실행한 후 DB Browser for SQLite에서 데이터 보기를 클릭하면 파이썬 코드에 의해 SQLite DB에 데이터가 저장된 걸 확인할 수 있습니다.

다음 코드는 SQLite 데이터베이스 데이터를 읽어오는 코드입니다. cursor를 사용하여 한 행씩 하나하나 읽어오는 방법과 fetchall() 함수를 사용하여 테이블의 모든 행을 반환받을 수 있습니다. cursor가 데이터의 끝에 도달한 경우 데이터를 더 이상 읽을 수 없게 되니 주의해야 합니다.

import sqlite3
import json
from pathlib import Path

# SQLite 연결 객체 생성: 매개변수는 데이터베이스 파일 명
with sqlite3.connect("db.sqlite3") as conn:
    command = "SELECT * FROM Movies"

    # SQLite 데이터베이스 읽어오기
    cursor = conn.execute(command)
    for row in cursor:
        print(row)

    # SQLite 데이터베이스 읽어오기: cursor의 fetchall() 함수 사용
    # 커서의 끝에 도달하면 아무것도 읽을 수 없으므로 주의
    movies = cursor.fetchall()  # 테이블의 모든 행을 하나로 반환
    print(movies)

시간 및 날짜 작업

Timestamps 작업

파이썬에서 시간 작업을 하려면 time 모듈을 사용합니다.

import time

print(time.time())  # 부동소수점 숫자: 초수

시간 계산은 특정 작업에 걸리는 시간을 계산할 때 사용할 수 있습니다.

import time

def send_emails():
    for i in range(100000):
        pass

start = time.time()
send_emails()
end = time.time()
duration = end - start
print(duration)

DateTimes 작업

파이썬에서 날짜 및 시간 작업을 하려면 datetime 모듈을 사용합니다.

날짜 및 시간 작업을 하는 경우 문자열의 형태를 분석하여 DateTimes 객체를 반환하는 strftime() 함수를 사용할 수 있습니다. 이 함수에서 사용되는 매개변수에 관해서는 https://docs.python.org/ko/3/library/datetime.html 를 참고하기 바랍니다.

from datetime import datetime
import time

# 날짜 객체 생성
dt = datetime(2019, 10, 12)  # 특정 날짜
dt = datetime.now()  # 현재 날짜
dt = datetime.strptime("2019/10/12", "%Y/%m/%d")  # 날짜 및 시간 문자열을 분석하여 날짜 객체 생성
dt = datetime.fromtimestamp(time.time())  # 타임스탬프 객체를 사용하여 날짜 객체 생성
print(dt)

# 날짜 객체엔 년, 월, 일 속성 존재
print(f"{dt.year}/{dt.month}/{dt.day}")

# strftime() 함수를 사용하여 날짜 출력
print(dt.strftime("%Y/%m/%d"))

# 날짜 객체도 연산 가능
yesterday = datetime(2019, 10, 11)
today = datetime(2019, 10, 12)
print(today - yesterday)  # 1 day, 0:00:00
print(today > yesterday)  # true

Time Deltas 작업

날짜 및 시간 객체도 연산이 가능합니다.

from datetime import datetime, timedelta

yesterday = datetime(2019, 10, 11)
today = datetime.now()

# 위의 두 날짜를 빼면 타임델타 객체가 됨
duration = today - yesterday

print(duration)
print(duration.days)  # duration 값 중 days 값만 출력
print(duration.seconds)  # duration 값 중 seconds 값만 출력
print(duration.total_seconds())  # duration 값 중 시, 분, 초 값을 모두 초 단위로 합산한 값 출력
from datetime import datetime, timedelta

dt1 = datetime(2019, 10, 11) + timedelta(days=1, seconds=1000)
dt2 = datetime.now()

# 위의 두 날짜를 빼면 타임델타 객체가 됨
duration = dt2 - dt1

print(duration)
print(duration.days)  # duration 값 중 days 값만 출력
print(duration.seconds)  # duration 값 중 seconds 값만 출력
print(duration.total_seconds())  # duration 값 중 시, 분, 초 값을 모두 초 단위로 합산한 값 출력

난수 생성

파이썬에서 난수 생성을 위해 random 모듈을 사용합니다.

import random
import string

print(random.random())  # 0~1 사이의 난수 생성
print(random.randint(1, 10))  # 두 정수 사이의 난수 생성
print(random.choice([1, 2, 3, 4]))  # 배열 중 아무 요소나 선택하여 출력

# 배열 중 아무 요소나 여러 개 선택하여 출력
print(random.choices([1, 2, 3, 4], k=2))
print(random.choices("asdfghjkl;", k=4))

# 문자열 중 아무 요소나 여러 개 선택한 후 다시 문자열로 재결합
print("".join(random.choices("asdfghjkl;", k=4)))
print(",".join(random.choices("asdfghjkl;", k=4)))  # 쉼표(,) 단위로 구분하여 문자열로 재결합

난수는 임의의 비밀번호를 생성하거나

import random
import string

alphabets = string.ascii_letters 
nums = string.digits
special_characters = "!@#$%^&*()"

rand1 = "".join(random.choices(alphabets + nums, k=9))
rand2 = "".join(random.choice(special_characters))
password = rand1 + rand2 # 9자리 알파벳+숫자 및 1자리 특수문자 조합의 랜덤 패스워드 생성

print(password)

배열을 뒤섞을 때 사용합니다.

import random
import string

numbers = [1, 2, 3, 4]
random.shuffle(numbers)  # 배열 뒤섞기
print(numbers)

웹 브라우저 열기

파이썬으로 웹 브라우저를 열기 위해 webbrowser 모듈을 사용합니다.

import webbrowser

webbrowser.open("https://google.com")

이메일 보내기

파이썬으로 이메일을 보내기 위해 MIME 헤더값을 정의하기 위한 MIMEMultipart 클래스, 메일 본문을 정의하기 위한 MIMEText 클래스 및 메일 전송을 위한 smtplib 모듈을 사용합니다.

본문만 들어있는 이메일 보내기

아래 코드는 Gmail을 사용하여 메일을 보내는 코드입니다. https://support.google.com/mail/answer/7126229 에서 발신메일(SMTP) 서버 정보를 확인한 후 아래 코드를 작성합니다.

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib

message = MIMEMultipart()

# 메일 헤더 값 정의. 이 헤더들은 MIME에 정의된 헤더.
message["from"] = "Ing-Yeo"  # 발신자
message["to"] = "test@test.com"  # 수신자 이메일
message["subject"] = "안녕요?ㅎ"  # 메일 제목

# 메일 본문 정의
message.attach(MIMEText("메일 전송 테스트입니다."))

# Gmail로 메일 전송
with smtplib.SMTP(host="smtp.gmail.com", port=587) as smtp:
    smtp.ehlo()  # Echo Hello. SMTP 서버 접속 요청.
    smtp.starttls()  # SMTP 연결 암호화를 위한 TLS 설정
    smtp.login("test@test.com", "P@ssW0rd!")  # 이메일을 전송할 Gmail 계정 및 패스워드 입력
    smtp.send_message(message)
    print("Sent...")

Username and Password not accepted. 에러가 발생하는 경우 https://myaccount.google.com/lesssecureapps 에서 보안 수준이 낮은 앱 사용을 허용해야 합니다.

이미지가 첨부된 이메일 보내기

메일에 이미지를 첨부하려면 MIMEImage 클래스와 pathlib 모듈을 사용하면 됩니다.

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from pathlib import Path
import smtplib

message = MIMEMultipart()

# 메일 헤더 값 정의. 이 헤더들은 MIME에 정의된 헤더.
message["from"] = "Ing-Yeo"  # 발신자
message["to"] = "test@test.com"  # 수신자 이메일
message["subject"] = "안녕요?ㅎ"  # 메일 제목

# body 헤더 값은 attach() 함수를 사용하여 정의
message.attach(MIMEText("메일 전송 테스트입니다."))

# 이미지 첨부
message.attach(MIMEImage(Path("jar_drip.jpg").read_bytes()))

with smtplib.SMTP(host="smtp.gmail.com", port=587) as smtp:
    smtp.ehlo()  # Echo Hello. SMTP 서버 접속 요청.
    smtp.starttls()  # SMTP 연결 암호화를 위한 TLS 설정
    smtp.login("test@test.com", "P@ssW0rd!")
    smtp.send_message(message)
    print("Sent...")

이메일 템플릿 사용하기

여러 개의 이메일을 보낼 때 특정 부분만 다르게 보내야 하는 경우가 있습니다. 예를 들어 똑같은 내용의 이메일을 받는 사람의 이름만 다르게 보내야 하는 경우가 있겠지요. 이런 경우 파이썬에서는 템플릿을 만든 후 string 모듈의 Template 클래스를 사용하면 됩니다.

먼저 이메일 템플릿으로 사용할 html 파일을 만듭니다. 매개변수인 항목에 달러($) 기호를 붙여 작성합니다.

  • template.html
<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
  <!-- $를 붙이면 매개변수가 됨 -->
  $name 님 안녕요?ㅎ 이 메일은 테스트 메일입니다.
</body>

</html>

그 다음 템플릿에 값을 지정한 후 이메일을 발송합니다. 템플릿에 값을 지정할 때 safe_substitute() 함수를 사용합니다.

  • app.py
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from pathlib import Path
from string import Template  # 템플릿
import smtplib

message = MIMEMultipart()

# 템플릿 가져오기
template = Template(Path("template.html").read_text())

# 메일 헤더 값 정의. 이 헤더들은 MIME에 정의된 헤더.
message["from"] = "Ing-Yeo"  # 발신자
message["to"] = "test@test.com"  # 수신자 이메일
message["subject"] = "안녕요?ㅎ"  # 메일 제목

# 템플릿에 값 지정
body = template.safe_substitute({"name": "Ing-Yeo"})  # name 매개변수에 값 지정

# body 헤더 값은 attach() 함수를 사용하여 정의
message.attach(MIMEText(body, "html"))  # body의 타입은 html
message.attach(MIMEImage(Path("jar_drip.jpg").read_bytes()))

with smtplib.SMTP(host="smtp.gmail.com", port=587) as smtp:
    smtp.ehlo()  # Echo Hello. SMTP 서버 접속 요청.
    smtp.starttls()  # SMTP 연결 암호화를 위한 TLS 설정
    smtp.login("test@test.com", "P@ssw0rd!")
    smtp.send_message(message)
    print("Sent...")

위의 코드를 실행하면 ‘Ing-YEO 님 안녕요?ㅎ 이 메일은 테스트 메일입니다.’ 라는 이메일이 전송됩니다.

명령줄 전달인자(Command-line Arguments)

파이썬 코드 실행 명령어를 통해 인자를 전달받을 수 있습니다.

다음 코드를 작성한 후 python3 app.py -a -b -c 명령어를 실행하면

  • app.py
import sys

print(sys.argv)

[‘/Users/ingyeo/Documents/Study/Python/HelloWorld/app.py’, ‘-a’, ‘-b’, ‘-c’] 과 같은 결과가 출력됩니다. 명령줄에 매개변수를 입력하면 sys.argv에 그 값이 지정되는 걸 확인할 수 있습니다.

아래 코드는 닉네임을 명령줄 전달인자로 받아 출력하는 코드입니다.

import sys

if len(sys.argv) == 1:
    print("USAGE: python3 app.py <nickname>")
else:
    nickname = sys.argv[1]
    print(f"{nickname} 님 안녕요?ㅎ")

외부 프로그램 실행

파이썬에서 외부 프로그램을 실행하려면 subprocess 모듈을 사용합니다.

모든 디렉터리 및 파일 목록을 출력하는 ls -l 명령어를 실행하는 파이썬 코드는 다음과 같습니다.

import subprocess

subprocess.run(["ls", "-l"])

run() 함수의 주요 매개변수는 다음과 같습니다.

  • capture_output: 실행 결과 터미널에 출력 여부(기본: False, 터미널에 출력됨)
  • text: 표준 출력 시 텍스트로 출력 여부(기본: False, Byte로 출력)
  • check: 오류가 발생하면 예외 발생 여부(기본: False, 예외를 발생시키지 않음)
import subprocess

try:
    completed = subprocess.run(["false"],
                               capture_output=True,  # 출력이 터미널에 찍히지 않게 함
                               text=True,  # 표준 출력시 텍스트로 출력
                               check=True)  # 오류가 발생하면 예외 발생
    print(type(completed))  # <class 'subprocess.CompletedProcess'>
    print(completed.args)  # ['ls', '-l']
    print(completed.returncode)  # 리턴코드 값이 0이면 성공, 1이면 실패
    print(completed.stderr)  # None
    print(completed.stdout)  # None

except subprocess.CalledProcessError as ex:
    print(ex)

댓글 남기기