모듈과 표준 라이브러리
Python은 무작위성, 수학, 날짜, 파일 경로 등 바로 사용할 수 있는 방대한 도구 모음을 함께 제공합니다. 이러한 도구들은 모듈에 들어 있으며, import로 코드에 가져옵니다. 이전 장에서 이미 import json을 사용해 보았습니다. 이 장에서는 import를 자세히 다루고 표준 라이브러리의 가장 유용한 부분을 소개합니다.
모듈 가져오기
가장 단순한 import는 모듈 전체를 가져와서 점 표기법으로 그 내용을 사용할 수 있게 해줍니다. 모듈에서 특정 이름만 가져와 접두사 없이 바로 사용할 수도 있습니다. 별칭(alias)은 긴 이름을 짧게 줄여줍니다.
import math
math.sqrt(16) # 4.0
math.pi # 3.141592653589793
math.floor(3.9) # 3
math.ceil(3.1) # 4모듈에서 특정 이름을 가져와서 바로 사용할 수 있습니다:
from math import sqrt, pi
sqrt(16) # 4.0 ("math." 접두사 불필요)
pi # 3.141592653589793모듈이나 이름에 별칭을 붙여 짧게 만들 수 있습니다:
import math as m
m.sqrt(16) # 4.0
from math import sqrt as square_root
square_root(25) # 5.0별칭은 인기 있는 서드파티 라이브러리에서 흔히 사용됩니다(import numpy as np, import pandas as pd). 표준 라이브러리 모듈에서는 전체 이름을 사용하는 것을 선호하세요; 코드를 더 읽기 쉽게 만듭니다.
random
random 모듈은 난수를 생성하고 무작위 선택을 합니다. 게임, 시뮬레이션, 무작위 샘플링 등 예측 불가능성이 필요한 모든 곳에 사용하세요. **시드(seed)**를 설정하면 결과를 재현할 수 있습니다: 동일한 시드는 매번 동일한 시퀀스를 생성합니다.
import random
random.random() # 0과 1 사이의 float (1 미포함)
random.randint(1, 10) # 1부터 10까지의 정수 (양쪽 포함)
random.uniform(1.0, 10.0) # 1.0과 10.0 사이의 float
colours = ["red", "green", "blue"]
random.choice(colours) # 항목 하나 선택
random.choices(colours, k=3) # k개 항목 선택 (중복 허용)
random.sample(colours, k=2) # k개 항목 선택 (중복 없음)
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers) # 제자리에서 섞고 None 반환재현 가능한 결과를 위해서는(테스트와 데이터 과학에서 유용) 생성 전에 시드를 설정합니다:
random.seed(42)
random.randint(1, 100) # 시드 42에 대해 항상 같은 값같은 시드는 어떤 기계에서도 매번 동일한 시퀀스를 생성합니다.
math
math 모듈은 기본 산술 연산자를 넘어서는 더 고급 수학 연산을 추가합니다. 제곱근, 거듭제곱, 로그, 삼각함수, 그리고 pi나 무한대 같은 특수 값들이 모두 여기 있습니다.
import math
math.sqrt(25) # 5.0
math.pow(2, 10) # 1024.0 (2 ** 10과 동일하지만 항상 float 반환)
math.log(100, 10) # 2.0 (밑 10 로그)
math.log(math.e) # 1.0 (자연 로그)
math.sin(math.pi / 2) # 1.0
math.cos(0) # 1.0
math.ceil(3.2) # 4
math.floor(3.9) # 3
math.trunc(3.9) # 3 (양수의 경우 int()와 동일)
math.inf # 무한대
math.isnan(float("nan")) # True
math.isinf(math.inf) # Truedatetime
datetime 모듈은 날짜와 시간을 다룹니다. datetime.now()는 현재 날짜와 시간을 알려줍니다. strftime()은 이를 문자열로 포맷합니다. strptime()은 문자열을 datetime으로 파싱합니다. timedelta는 더하거나 뺄 수 있는 기간을 나타냅니다.
from datetime import datetime, date, timedelta
now = datetime.now() # 현재 날짜와 시간
today = date.today() # 현재 날짜만
print(now.year, now.month, now.day)
print(now.hour, now.minute, now.second)
# 포맷팅
print(now.strftime("%Y-%m-%d")) # "2024-01-15"
print(now.strftime("%d %B %Y, %H:%M")) # "15 January 2024, 09:42"
# 파싱
deadline = datetime.strptime("2024-12-31", "%Y-%m-%d")
# 산술 연산
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
diff = deadline - now
print(f"{diff.days} days until deadline")자주 사용되는 strftime 코드:
| 코드 | 의미 | 예시 |
|---|---|---|
%Y | 4자리 연도 | 2024 |
%m | 월 (0 패딩) | 01 |
%d | 일 (0 패딩) | 15 |
%H | 시 (24시간) | 09 |
%M | 분 | 42 |
%B | 전체 월 이름 | January |
os와 pathlib
pathlib은 파일 경로를 다루는 현대적인 방법입니다. Path 객체를 사용하면 / 연산자로 경로를 구축하고, 검사하고, 탐색할 수 있습니다. os는 환경 변수와 더 저수준의 OS 연산에 대한 접근을 제공합니다. 새 코드에는 pathlib을 선호하세요.
from pathlib import Path
p = Path("data/reports")
p.exists() # 경로가 존재하면 True
p.is_dir() # 디렉터리면 True
p.is_file() # 파일이면 True
p.mkdir(parents=True, exist_ok=True) # 디렉터리 생성
for f in p.glob("*.csv"): # 디렉터리 내 모든 CSV 파일
print(f.name) # 파일 이름만
report = p / "report_jan.csv" # / 연산자가 경로를 결합
report.stem # "report_jan" (확장자 없는 이름)
report.suffix # ".csv"
report.parent # Path("data/reports")
content = report.read_text() # 파일 내용을 직접 읽기
report.write_text("new content\n") # 직접 쓰기os 모듈의 경우:
import os
os.getcwd() # 현재 작업 디렉터리
os.listdir(".") # 디렉터리 내용 목록
os.path.exists("data.txt") # 경로가 존재하면 True
os.path.join("data", "file.txt") # "data/file.txt" (크로스플랫폼)
os.environ.get("HOME") # 환경 변수 읽기새 코드에는 pathlib을 선호하세요. 환경 변수가 필요하거나 문자열을 기대하는 오래된 API를 다룰 때 os를 사용하세요.
timeit
timeit은 코드 실행에 걸리는 시간을 측정합니다. 두 가지 접근 방식을 비교하여 더 빠른 것을 선택하고 싶을 때 유용합니다. 안정적인 측정값을 얻으려면 코드를 여러 번 실행하세요.
import timeit
# 단일 문장의 시간 측정
timeit.timeit("sum(range(1000))", number=10000)
# 더 복잡한 블록의 시간 측정
setup = "data = list(range(1000))"
code = "[x * 2 for x in data]"
time = timeit.timeit(code, setup=setup, number=10000)
print(f"{time:.4f} seconds for 10,000 runs")number는 반복할 횟수입니다. 반복이 많을수록 더 안정적인 측정값이 나옵니다.
string
string 모듈은 문자, 숫자, 구두점에 대한 미리 정의된 문자열 상수를 제공합니다. 문자를 확인하거나 특정 알파벳에서 무작위 문자열을 생성해야 할 때 유용합니다.
import string
string.ascii_lowercase # "abcdefghijklmnopqrstuvwxyz"
string.ascii_uppercase # "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
string.ascii_letters # 둘을 결합
string.digits # "0123456789"
string.punctuation # 모든 구두점 문자문자를 확인하거나 무작위 문자열을 생성해야 할 때 유용합니다:
import string, random
chars = string.ascii_letters + string.digits
password = "".join(random.choices(chars, k=12))직접 모듈 만들기
모든 Python 파일이 모듈입니다. 다른 파일에서 사용하려면 파일 이름(.py 제외)으로 가져옵니다. 모듈 전체를 가져와 점 표기법으로 그 내용을 사용하거나, 특정 이름을 직접 가져올 수 있습니다.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
PI = 3.14159# main.py
import utils
utils.clamp(150, 0, 100) # 100
utils.PI # 3.14159
from utils import clamp
clamp(50, 0, 100) # 50Python은 임포트하는 파일과 같은 디렉터리(그리고 몇 군데 다른 곳)에서 모듈을 찾습니다. 더 큰 프로젝트의 경우 모듈은 패키지로 구성됩니다: __init__.py 파일이 있는 디렉터리입니다.
__name__ == "__main__"
Python이 파일을 직접 실행할 때 __name__은 "__main__"으로 설정됩니다. 같은 파일이 모듈로 임포트될 때는 __name__이 모듈 이름입니다. 이 패턴을 사용하면 파일을 직접 실행할 때 동작하지만 다른 모듈에서 임포트할 때는 건너뛰는 코드를 작성할 수 있습니다.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
if __name__ == "__main__":
# 이는 다음을 실행할 때만 동작: python utils.py
# 다음을 할 때는 동작하지 않음: import utils
print(clamp(150, 0, 100)) # 100이는 독립 스크립트로도 유용한 모든 모듈에 대한 표준 패턴입니다.
표준 라이브러리 주요 모듈
알아두면 좋은 몇 가지 모듈이 더 있습니다. 각각 직접 구현하려면 상당한 작업이 필요한 일반적인 문제를 해결합니다.
collections: 특수화된 컨테이너 타입:
from collections import Counter, defaultdict, deque
Counter(["a", "b", "a", "c", "a"]) # Counter({'a': 3, 'b': 1, 'c': 1})
defaultdict(list) # 누락된 키를 자동 생성하는 dict
deque([1, 2, 3], maxlen=5) # 양쪽 끝에서 빠른 append/popitertools: 이터러블 작업을 위한 도구:
import itertools
list(itertools.chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(itertools.islice(range(100), 5)) # [0, 1, 2, 3, 4]
list(itertools.combinations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 3)]
list(itertools.product([0, 1], repeat=2)) # [(0,0), (0,1), (1,0), (1,1)]sys: Python 인터프리터에 대한 접근:
import sys
sys.argv # 명령줄 인자 목록
sys.exit(1) # 상태 코드와 함께 종료
sys.version # Python 버전 문자열서드파티 패키지: 표준 라이브러리를 넘어, pip로 커뮤니티 패키지를 설치합니다:
pip install requests # HTTP 라이브러리
pip install pandas # 데이터 조작
pip install numpy # 수치 계산서드파티 패키지는 이 가이드의 범위를 벗어나지만, 패턴은 항상 같습니다: pip install 후 import.
실전 예제
random, string, datetime을 결합하여 타임스탬프가 포함된 고유 게임 ID 생성:
import random
import string
from datetime import datetime
def generate_game_id(length: int = 8) -> str:
chars = string.ascii_uppercase + string.digits
return "".join(random.choices(chars, k=length))
def timestamp() -> str:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
game_id = generate_game_id()
print(f"[{timestamp()}] Starting game {game_id}")
scores = [random.randint(50, 100) for _ in range(5)]
print(f"Round scores: {scores}")
print(f"Best: {max(scores)}")
