[PY-009][중급] 데이터를 하나씩 처리하고 안전하게 닫기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[PY-009][중급] 데이터를 하나씩 처리하고 안전하게 닫기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 126회 작성일 26-09-03 23:33

본문

[이번 수업]

데이터를 전부 목록으로 만든 뒤 처리하지 않고, 필요한 값을 한 개씩 꺼내 쓰는 방법을 배웁니다. 이터레이터는 다음 값을 기억하며 전달하고, 제너레이터는 이터레이터를 간단히 만드는 함수입니다. 컨텍스트 관리자는 파일처럼 사용 뒤 정리가 필요한 자원의 시작과 종료를 맡습니다.

[선수지식]

함수, for 반복문, 예외 처리의 기초가 필요합니다. PY-004와 PY-007을 먼저 읽으면 좋습니다.

[학습목표]

1. 이터러블과 이터레이터의 차이를 설명합니다.
2. yield로 값을 하나씩 만드는 제너레이터를 작성합니다.
3. with 문으로 자원이 정리되는 범위를 표시합니다.

[핵심개념]

이터러블은 반복할 수 있는 대상입니다. 리스트, 문자열, 파일 등이 해당하며 `iter(대상)`을 호출하면 이터레이터를 얻습니다. 이터레이터는 현재 위치를 기억하고 `next()`가 호출될 때 다음 값을 줍니다. 값이 끝나면 StopIteration 예외로 종료를 알리며, for 문은 이 과정을 자동으로 처리합니다.

제너레이터 함수에는 `return` 대신 흐름을 잠시 멈추는 `yield`가 있습니다. 함수를 호출하면 결과 전체가 아니라 제너레이터 객체가 생깁니다. `next()`가 호출될 때까지 본문은 진행되지 않고, yield에서 값을 내보낸 뒤 위치와 지역 변수를 기억합니다. 그래서 큰 입력을 한꺼번에 메모리에 올리지 않는 처리 흐름을 만들 수 있습니다. 다만 한 번 끝까지 소비한 제너레이터는 처음부터 다시 쓸 수 없습니다.

컨텍스트 관리자는 `with` 블록에 들어갈 때 `__enter__`, 나갈 때 `__exit__` 동작을 제공합니다. 정상 종료뿐 아니라 블록 안에서 예외가 나도 시작에 성공한 컨텍스트의 종료 동작이 호출됩니다. 파일 닫기, 잠금 해제처럼 빠뜨리기 쉬운 정리를 한곳에 모을 수 있습니다.

[따라하기]

아래 내용을 stream_demo.py로 저장합니다. StringIO는 문자열을 파일처럼 읽게 해 주는 메모리 안의 텍스트 스트림입니다.

```python
from io import StringIO

def read_numbers(stream):
    for line in stream:
        cleaned = line.strip()
        if cleaned:
            yield int(cleaned)

with StringIO("10\n\n20\n30\n") as stream:
    numbers = read_numbers(stream)
    print(f"iterator={iter(numbers) is numbers}")
    print(f"first={next(numbers)}")
    print(f"remaining_sum={sum(numbers)}")

print(f"closed={stream.closed}")
```

Windows는 `py stream_demo.py`, macOS와 Linux는 `python3 stream_demo.py`로 실행합니다. 외부 패키지는 필요 없습니다. 예상 결과는 다음과 같습니다.

```text
iterator=True
first=10
remaining_sum=50
closed=True
```

`read_numbers(stream)`을 호출한 직후에는 줄을 읽지 않습니다. 첫 next가 10을 꺼내고, sum이 남은 20과 30을 소비합니다. with 블록이 끝난 뒤 `closed=True`가 출력되어 스트림이 정리된 것도 확인할 수 있습니다.

[흔한 실수]

제너레이터를 목록처럼 여러 번 반복하면 두 번째에는 값이 남지 않을 수 있습니다. 끝난 이터레이터에 next를 직접 호출하면 StopIteration이 발생합니다. 파일을 with 블록에서 닫은 뒤 그 파일을 읽는 제너레이터만 밖으로 반환하면 실제 반복 시점에는 파일이 이미 닫혀 있습니다. 제너레이터가 자원을 사용하는 동안 with 범위도 유지해야 합니다.

[보안 주의]

본인 소유의 로컬·격리 환경에서 공개 가능한 데이터로 실습합니다. 한 항목씩 읽어도 입력 크기, 줄 길이, 항목 수 제한이 자동으로 생기지는 않습니다. 외부 문자열을 int로 바꿀 때 ValueError를 처리하고 허용 범위를 검사하세요. 외부에서 받은 파일 경로를 그대로 열지 말고 허용된 기준 폴더 안인지 확인하며, 예외를 무조건 숨기는 컨텍스트 관리자는 피합니다.

[직접 해볼 과제]

입력 문자열에 `oops`와 `-5`를 추가하세요. read_numbers가 숫자가 아닌 줄은 개수를 세고 건너뛰며, 0보다 큰 숫자만 yield하도록 바꿉니다. 기존 출력 순서를 유지하고 마지막에 건너뛴 줄 수를 출력해 보세요.

[확인문제]

1. next를 호출하기 전 제너레이터 함수의 본문은 어디까지 실행되나요?
2. 예제에서 first를 출력한 뒤 sum이 더하는 값은 무엇인가요?
3. 파일을 읽는 제너레이터와 with 블록의 수명을 함께 유지해야 하는 이유는 무엇인가요?

[다음 학습]

다음은 JSTS-009 Node.js 파일·프로세스·네트워크 API입니다. JavaScript 실행 환경에서 운영체제 자원을 다루는 기본 인터페이스를 익힙니다.

[공식 참고 자료]

Python 이터레이터 형식
https://docs.python.org/3/library/stdtypes.html#iterator-types

Python 제너레이터 안내
https://docs.python.org/3/howto/functional.html#generators

Python with 문 언어 참조
https://docs.python.org/3/reference/compound_stmts.html#the-with-statement

Python contextlib 공식 문서
https://docs.python.org/3/library/contextlib.html

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,858
어제
6,862
최대
16,772
전체
770,809
Copyright © 소유하신 도메인. All rights reserved.