io — 스트림 작업을 위한 핵심 도구
io — 스트림 작업을 위한 핵심 도구
io 모듈은 다양한 유형의 I/O를 다루기 위한 파이썬의 주요 기능을 제공해요. 세 가지 주요 I/O 유형이 있어요: 텍스트 I/O, 바이너리 I/O, 그리고 원시(raw) I/O. 이들은 일반적인 범주이며 각각에 다양한 백킹 저장소가 사용될 수 있어요. 이 범주 중 어느 것에 속하는 구체적인 객체를 파일 객체(file object)라고 불러요. 다른 일반 용어로는 스트림(stream)과 파일 유사 객체(file-like object)가 있어요.
카테고리와 무관하게 각 구체적인 스트림 객체는 다양한 능력을 가져요: 읽기 전용, 쓰기 전용, 또는 읽기-쓰기가 될 수 있고, 임의 랜덤 접근(앞뒤로 어느 위치든 시크)을 허용하거나 순차 접근만(예: 소켓이나 파이프) 허용할 수 있어요.
모든 스트림은 주는 데이터 타입에 주의해요. 예를 들어 바이너리 스트림의 write() 메서드에 str 객체를 주면 TypeError가 발생해요. 텍스트 스트림의 write()에는 bytes 객체를 주는 것도 마찬가지예요.
버전 3.3에서 변경: 이전에 IOError를 발생시키던 연산이 이제 OSError를 발생시켜요. IOError는 이제 OSError의 별칭이기 때문이에요.
본문
개요
텍스트 I/O는 str 객체를 기대하고 생성해요. 즉 백킹 저장소가 본래 바이트로 만들어질 때마다(파일의 경우처럼) 데이터의 인코딩·디코딩이 투명하게, 그리고 플랫폼별 줄 바꿈 문자의 선택적 변환이 이루어져요. 텍스트 스트림을 만드는 가장 쉬운 방법은 open()에 선택적으로 인코딩을 지정하는 것이에요:
f = open("myfile.txt", "r", encoding="utf-8")
인메모리 텍스트 스트림도 StringIO 객체로 사용할 수 있어요: f = io.StringIO("some initial text data").
바이너리 I/O(버퍼 I/O라고도 함)는 bytes 유사 객체를 기대하고 bytes 객체를 생성해요. 인코딩, 디코딩, 줄 바꿈 변환이 수행되지 않아요. 바이너리 스트림을 만드는 가장 쉬운 방법은 모드 문자열에 'b'가 있는 open()을 사용하는 것이에요:
f = open("myfile.jpg", "rb")
인메모리 바이너리 스트림은 BytesIO 객체로 사용할 수 있어요: f = io.BytesIO(b"some initial binary data: \x00\x01").
원시 I/O(버퍼 없는 I/O라고도 함)는 일반적으로 바이너리와 텍스트 스트림의 저수준 구성 요소로 사용되며, 사용자 코드에서 원시 스트림을 직접 조작하는 것은 거의 유용하지 않아요. 버퍼링을 비활성화해 바이너리 모드로 파일을 열어 원시 스트림을 만들 수 있어요:
f = open("myfile.jpg", "rb", buffering=0)
경고: 원시 I/O는 저수준 인터페이스이며, 메서드는 보통 반환값을 확인하고 명시적으로 재시도해 작업 완료를 보장해야 해요. 예를 들어 write()는 제공된 바이트 수보다 적을 수 있는(부분 쓰기) 쓰인 바이트 수를 반환해요. 바이너리 I/O와 텍스트 I/O 같은 고수준 I/O 객체는 재시도 동작을 구현해요.
텍스트 인코딩
TextIOWrapper와 open()의 기본 인코딩은 로케일별(locale.getencoding())이에요. 그러나 많은 개발자가 대부분의 Unix 플랫폼이 기본적으로 UTF-8 로케일을 사용하므로 UTF-8로 인코딩된 텍스트 파일(예: JSON, TOML, Markdown)을 열 때 인코딩을 지정하는 것을 잊어요. 대부분의 Windows 사용자에게 로케일 인코딩이 UTF-8이 아니므로 이는 버그를 유발해요. 텍스트 파일을 열 때 인코딩을 명시적으로 지정하는 것이 적극 권장돼요. UTF-8을 사용하려면 encoding="utf-8"을 전달해요. 파이썬 3.10부터 현재 로케일 인코딩을 사용하려면 encoding="locale"이 지원돼요.
옵트인 EncodingWarning: 기본 로케일 인코딩이 사용되는 곳을 찾으려면 -X warn_default_encoding 명령줄 옵션을 활성화하거나 PYTHONWARNDEFAULTENCODING 환경 변수를 설정할 수 있으며, 기본 인코딩이 사용될 때 EncodingWarning을 발생시켜요.
고수준 모듈 인터페이스
io.DEFAULT_BUFFER_SIZE — 모듈의 버퍼 I/O 클래스가 사용하는 기본 버퍼 크기를 포함하는 int.
io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) — 내장 open() 함수의 별칭이에요.
io.open_code(path) — 제공된 파일을 모드 'rb'로 열어요. 내용을 실행 코드로 취급하려는 의도일 때 이 함수를 사용해야 해요. 버전 3.8에서 추가됨.
io.text_encoding(encoding, stacklevel=2, /) — open()이나 TextIOWrapper를 사용하고 encoding=None 파라미터를 가진 호출 가능 객체를 위한 헬퍼 함수예요. encoding이 None이 아니면 그 값을 반환하고, 아니면 UTF-8 모드에 따라 "locale" 또는 "utf-8"을 반환해요. sys.flags.warn_default_encoding이 참이고 encoding이 None이면 EncodingWarning을 발생시켜요. 버전 3.10에서 추가됨.
exception io.BlockingIOError — 내장 BlockingIOError 예외의 호환 별칭.
exception io.UnsupportedOperation — 스트림에서 지원되지 않는 연산이 호출될 때 발생하는, OSError와 ValueError를 상속하는 예외.
클래스 계층
I/O 스트림의 구현은 클래스의 계층으로 구성돼요. 먼저 스트림의 다양한 범주를 지정하는 데 사용되는 추상 기본 클래스(ABC)가 있고, 그다음 표준 스트림 구현을 제공하는 구체적인 클래스가 있어요.
I/O 계층의 맨 위에는 추상 기본 클래스 IOBase가 있어요. RawIOBase ABC는 IOBase를 확장하며 스트림에 대한 바이트 읽기·쓰기를 다뤄요. FileIO는 RawIOBase를 하위 분류해 기계의 파일 시스템에 있는 파일에 대한 인터페이스를 제공해요. BufferedIOBase ABC는 IOBase를 확장하며 원시 바이너리 스트림(RawIOBase)에서의 버퍼링을 다뤄요. TextIOBase ABC는 IOBase를 확장하며 바이트가 텍스트를 나타내는 스트림을 다루고 문자열로/에서 인코딩·디코딩을 처리해요.
I/O 기본 클래스
class io.IOBase — 모든 I/O 클래스의 추상 기본 클래스. 파생 클래스가 선택적으로 오버라이드할 수 있는 많은 메서드의 빈 추상 구현을 제공하며, 기본 구현은 읽거나 쓰거나 시크할 수 없는 파일을 나타내요. IOBase(및 하위 클래스)는 이터레이터 프로토콜을 지원하고 컨텍스트 매니저이므로 with 문을 지원해요.
제공하는 주요 메서드: close(), closed, fileno(), flush(), isatty(), readable(), readline(), readlines(), seek(), seekable(), tell(), truncate(), writable(), writelines(), __del__().
class io.RawIOBase — 원시 바이너리 스트림의 기본 클래스. IOBase를 상속해요. read(), readall(), readinto(b), write(b)를 제공해요.
class io.BufferedIOBase — 어떤 종류의 버퍼링을 지원하는 바이너리 스트림의 기본 클래스. IOBase를 상속해요. raw, detach(), read(), read1(), readinto(b), readinto1(b), write(b)를 제공해요.
원시 파일 I/O
class io.FileIO(name, mode='r', closefd=True, opener=None) — 바이트 데이터를 포함하는 OS 수준 파일을 나타내는 원시 바이너리 스트림. RawIOBase를 상속해요. name은 열 파일의 경로를 나타내는 문자열 또는 bytes 객체이거나, 기존 OS 수준 파일 디스크립터의 번호를 나타내는 정수가 될 수 있어요. mode는 읽기(기본값) 'r', 쓰기 'w', 독점 생성 'x', 추가 'a'가 될 수 있어요. 모드에 '+'를 추가하면 동시 읽기·쓰기가 가능해요. FileIO는 저수준 I/O 객체이므로 read()와 write()의 반환값을 재시도 루프에서 명시적으로 확인해야 해요.
버퍼 스트림
class io.BytesIO(initial_bytes=b'') — 인메모리 bytes 버퍼를 사용하는 바이너리 스트림. BufferedIOBase를 상속해요. getbuffer()(복사 없이 버퍼 내용의 읽기·쓰기 가능한 뷰 반환)와 getvalue()(버퍼의 전체 내용 포함 bytes 반환)를 제공해요.
class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE) — 읽기 가능한 비시크 가능 RawIOBase 원시 바이너리 스트림에 더 높은 수준의 접근을 제공하는 버퍼 바이너리 스트림. peek()와 read()를 제공해요.
class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE) — 쓰기 가능한 비시크 가능 RawIOBase 원시 바이너리 스트림에 더 높은 수준의 접근을 제공하는 버퍼 바이너리 스트림. flush()와 write()를 제공해요.
class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE) — 시크 가능한 RawIOBase 원시 바이너리 스트림에 더 높은 수준의 접근을 제공하는, BufferedIOBase 인터페이스를 구현하는 버퍼 바이너리 스트림.
class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /) — 비시크 가능한 두 RawIOBase 원시 바이너리 스트림(하나 읽기, 하나 쓰기)에 더 높은 수준의 접근을 제공하는 버퍼 바이너리 스트림.
텍스트 I/O
class io.TextIOBase — 텍스트 스트림의 기본 클래스. 스트림 I/O에 문자 및 줄 기반 인터페이스를 제공하며 IOBase를 상속해요. encoding, errors, newlines, buffer 속성과 detach(), read(), readline(), seek(), tell(), write() 메서드를 제공해요.
class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False) — BufferedIOBase 버퍼 바이너리 스트림에 더 높은 수준의 접근을 제공하는 버퍼 텍스트 스트림. TextIOBase를 상속해요. encoding은 스트림이 디코딩·인코딩할 인코딩 이름이며(UTF-8 모드에서 기본 UTF-8, 아니면 locale.getencoding()), errors는 인코딩·디코딩 오류 처리 방법을 지정하며, newline은 줄 끝 처리 방법을 제어하고, line_buffering이 True면 write에 줄 바꿈이 포함될 때 flush()가 암시되며, write_through가 True면 write() 호출이 버퍼링되지 않음을 보장해요.
class io.StringIO(initial_value='', newline='\n') — 인메모리 텍스트 버퍼를 사용하는 텍스트 스트림. TextIOBase를 상속해요. getvalue()(버퍼 전체 내용 포함 str 반환)를 제공해요.
class io.IncrementalNewlineDecoder — 유니버설 뉴라인 모드를 위해 줄 바꿈을 디코딩하는 헬퍼 코덱. codecs.IncrementalDecoder를 상속해요.
성능
버퍼 I/O는 사용자가 단일 바이트를 요청해도 큰 데이터 청크만 읽고 씀으로써 운영 체제의 버퍼 없는 I/O 루틴을 호출·실행하는 비효율성을 숨겨요. 결과적으로 바이너리 데이터에는 버퍼 없는 I/O보다 버퍼 I/O를 사용하는 것이 거의 항상 바람직해요. 텍스트 I/O는 유니코드와 바이너리 데이터 간 변환이 필요하므로 같은 저장소에 대한 바이너리 I/O보다 훨씬 느려요.
FileIO 객체는 운영 체제 호출이 스레드 안전한 만큼 스레드 안전하고, 바이너리 버퍼 객체는 내부 구조를 잠금으로 보호해 여러 스레드에서 안전하게 호출할 수 있어요. TextIOWrapper 객체는 스레드 안전하지 않아요.
정적 타이핑
class io.Reader[T] — 파일이나 다른 입력 스트림에서 읽기 위한 일반 프로토콜. T는 보통 str 또는 bytes예요. class io.Writer[T] — 파일이나 다른 출력 스트림에 쓰기 위한 일반 프로토콜. 버전 3.14에서 추가됨.