python 데코레이터, 로깅, 병렬성 프로그래밍

차지예·2025년 5월 19일

생성AI

목록 보기
5/56
post-thumbnail

클로저, 데코레이터 차이 알기!

🟡클로저(Closure)

클로저는 외부 함수의 변수를 내부 함수가 참조하고 있을 때, 외부 함수가 종료되어도 해당 변수에 접근할 수 있는 함수이다.

➡️ 즉, 내부 함수가 외부 함수의 스코프에 있는 변수들을 기억하고 있는 상태를 말한다.


def outer(out1):
  def inner(in1):
    print("inner call")
    print("outer argument: ", in1)
    out1()   # 여기서 out1은 hello 함수
  return inner

def hello():
  print("hello")

f = outer(hello) 
f(10)
inner call
outer argument:  10
hello

실행 순서

  1. f = outer(hello) 호출됨
    outer(hello)가 호출되면서 hello 함수 자체가 out1으로 전달됨.
    inner(in1)이라는 내부 함수를 정의하고, 이 함수를 리턴함.

즉, f에는 inner 함수가 저장됨.
👉 f = inner가 된 것임.

  1. f(10) → 즉 inner(10) 실행됨
    inner 함수가 호출되며 in1 = 10이 전달됨.
    순서대로 다음이 실행됨:
    print("inner call") → 출력: inner call
    print("outer argument: ", in1) → 출력: outer argument: 10
    out1() 호출됨 → out1은 처음에 넘겨준 hello 함수이므로 hello() 호출
    hello()print("hello") 실행 → 출력: hello

❓ 왜 클로저인가?

outer() 함수가 끝나도 x = 10을 기억하고 있다.
이 x는 inner() 함수 내부에서 계속 사용할 수 있다.


🟡데코레이터(Decorator)

데코레이터는 기존 함수에 기능을 추가할 때 사용하는 문법입니다.
클로저 개념을 활용해서, 함수 실행 전후에 다른 기능을 넣을 수 있어요.

def decorator(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")
    return wrapper

@decorator  # say_hello = decorator(say_hello)
def say_hello():
    print("안녕하세요!")

say_hello()
함수 실행 전
안녕하세요!
함수 실행 후

@decorator

@decorator는 say_hello() 함수를 decorator() 함수에 넣어 새로운 함수로 바꿔주는 문법이에요.

➡️ 즉, say_hello = decorator(say_hello) 와 동일합니다.

데코레이터 안의 wrapper()가 클로저처럼 func를 기억하고 있기 때문에 작동하는 거예요.

✅ 요약

개념클로저데코레이터
핵심 기능외부 변수 기억함수에 기능 추가
필요한 구조함수 안의 함수함수 안의 함수 (클로저 활용)
주요 사용처상태 유지로깅, 권한 확인, 실행 시간 측정 등
# 실행 시간 측정 데코레이터
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"실행 시간: {end - start:.4f}초")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)
    print("실행 완료")

slow_function()

🟡로깅

  • 프로그램이 실행되는 동안 발생하는 이벤트, 에러, 경고, 정보 등을 기록하는 것.
  • print()보다 체계적이다.
  • 파일로 저장하거나 콘솔에 출력하거나, 다양한 방법으로 로그를 남길 수 있다.
레벨의미로깅 함수
DEBUG디버깅 용도로 사용 (가장 낮음)debug()
INFO일반 정보 출력용info()
WARNING경고, 문제 될 가능성 있음warning()
ERROR에러 발생error()
CRITICAL치명적인 문제 (프로그램 중단 가능)critical()

🟡쓰레드

프로세스와 스레드의 개념

프로세스: 운영체제가 프로그램 실행을 위해 제공하는 독립된 실행 공간이다

스레드: 프로세스 내에서 실행되는 작업의 단위로, 여러 스레드가 하나의 프로세스 자원을 공유하며 동시에 실행될 수 있다.

스레드란?

스레드는 프로세스 내에서 실행되는 작업 단위로, 멀티스레딩을 통해 하나의 프로그램이 여러 작업을 동시에 수행할 수 있다.

운영체제는 스레드를 스케줄링하여 CPU 자원을 효율적으로 분배한다..

데몬 스레드 만들기

데몬 스레드: 메인 스레드가 종료되면 자동으로 종료되는 스레드이다
서브 스레드를 데몬으로 설정하려면 daemon 속성을 True로 설정한다.

Fork와 Join

Fork: 메인 스레드에서 새로운 서브 스레드를 생성하는 과정이다.
Join: 메인 스레드가 서브 스레드의 작업이 완료될 때까지 기다리는 메서드이다.


🟡멀티프로세싱

메인 프로세스(Main Process)

파이썬 스크립트를 실행하면 기본적으로 하나의 메인 프로세스가 생성된다.
multiprocessing.current_process() 함수를 사용하여 현재 프로세스의 이름과 PID(Process ID)를 확인할 수 있다.

import multiprocessing as mp

if __name__ == "__main__":
    proc = mp.current_process()
    print(proc.name)  # 프로세스 이름
    print(proc.pid)   # 프로세스 ID

프로세스 스포닝(Spawning)

부모 프로세스가 자식 프로세스를 생성하는 과정을 스포닝이라고 한다.

multiprocessing.Process 클래스를 사용하여 새로운 프로세스를 생성하고, start() 메서드를 호출하여 실행한다.

import multiprocessing as mp
import time

def worker():
    proc = mp.current_process()
    print(proc.name)
    print(proc.pid)
    time.sleep(5)
    print("SubProcess End")

if __name__ == "__main__":
    proc = mp.current_process()
    print(proc.name)
    print(proc.pid)

    p = mp.Process(name="SubProcess", target=worker)
    p.start()

    print("MainProcess End")

더 정확한 코드는 "git hub"

0개의 댓글