본문 바로가기

알고리즘 풀이

파이썬 sys.stdin.readline 써도 시간초과? 느린 이유 3가지와 os.read 완전 정복 (입출력 최적화)

SMALL

 

파이썬 입출력 최적화 총정리

 

혹시 "sys.stdin.readline으로 바꿨는데도 시간초과가 뜨셨나요? 

코딩 문제, PS를 풀다 보면 readline만으로는 부족한 경우가 있습니다."

 

제출 결과가 Time Limit Exceeded (TLE)로 나온다면, 알고리즘 문제가 아니라 입출력 속도 문제일 가능성이 높습니다.

 

이 글에서는

  • readline보다 빠른 read().split()
  • 숨겨진 병목 map(int)
  • 최상위 속도의 os.read 기법

3가지를 코딩 테스트에서 실제로 시간 초과를 줄이는 입출력 최적화 방법을 단계별로 정리하여 보여주고

python 입력 방식 속도 비교

마지막에는 최적화 템플릿 코드를 제공합니다.

 

1. readline보다 빠른 read(). split()

 

많은 분들이 아래처럼 쓰고 있습니다.

 

import sys
input = sys.stdin.readline

이 방식은 input()보다는 빠르지만, 입력이 수십만 개 이상이면 여전히 느립니다.

이유는 단순합니다.

 

시스템 콜 횟수

 

readline \ 입력 줄 수만큼 반복 호출
read 단 1번

시스템 콜(OS에 입력을 요청하는 행위)이 반복될수록 오버헤드가 쌓입니다.

이렇게 오버헤드가 생기면 당연히 코드의 실행시간은 계속 증가할수 밖에,,,,, 없습니다.

해결책은 처음부터 전부 읽어오는 것입니다.

 
import sys
data = sys.stdin.read().split()
 

read()는 표준 입력 전체를 한 번에 문자열로 읽고, split()으로 공백/개행 단위로 분리합니다.

 

이후 data [0], data [1] 식으로 인덱스방식으로 접근하면 됩니다.

 

 

2. map(int)의 숨겨진 병목 — Lazy 처리

 

아래 코드, 많이 사용되는 코드입니다.

 
a = list(map(int, input().split()))
 

 

문제는 이 코드가 리스트의 모든 요소를 즉시 int로 변환한다는 점입니다.

만약 100만 개 중 앞의 2개의 값만 필요한 상황이라면, 나머지 99만 9천 개의 변환은 시간만 늘리게 됩니다.

개선 방법: 필요할 때만 변환 (Lazy 처리)

 
 
import sys
data = sys.stdin.read().split()

# 필요한 시점에만 변환
n = int(data[0])
m = int(data[1])


Lazy 처리란?
데이터를 미리 전부 처리하지 않고, 실제로 필요한 시점에만 연산을 수행하는 기법입니다. 초기 로딩 속도를 높이고 불필요한 계산을 줄여 전체 성능을 최적화합니다.


 

data 배열에는 문자열 그대로 저장해 두고, int()는 실제로 해당 값이 필요한 순간에만 호출하는 것이 핵심입니다.

 

 

 

 

 

3. os.read — 가장 빠른 입력 방식

속도가 최우선이라면 이 방법이 좋습니다.

 

import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

왜 이렇게 빠를까?

  • os.read(0,...) → OS 레벨에서 파일 디스크립터 0번(표준 입력)을 직접 읽음
  • os.fstat(0). st_size → 입력 파일의 정확한 크기를 미리 파악해 딱 그만큼만 읽음
  • io.BytesIO → 메모리 버퍼에 올려두고 readline으로 줄 단위 접근

Python 내부 파서를 거치지 않고 OS와 직접 통신하기 때문에 일반 input()보다 수십 배 빠릅니다

 

 

주의사항: 로컬 IDE 환경에서는 표준 입력이 파일 형태가 아니라 오류가 날 수 있습니다. 백준, 프로그래머스 등

채점 환경에서만 사용하세요.

 

 

4. 출력도 느릴 수 있다 — print 반복 호출 문제

입력만큼 출력도 시간을 줄이는데 중요한 비중을 차지합니다.

 
 
 

print()는 호출할 때마다 출력 버퍼를 flush 하기 때문에 N번 호출하면 N번의 I/O가 발생합니다.

 
 
python
#느린 방식: print를 N번 호출
for i in range(n):
    print(i)

 

문자열 리스트에 결과를 모아둔 뒤, "\n". join()으로 한 번에 연결해 출력합니다.

print() 호출이 1번으로 줄어들어 출력 속도가 크게 향상됩니다.

 

for i in range(n):
print(i)

#print의 반복 -> 출력 시간의 증가

result = []
for i in range(n):
	result.append(str(i))
print("\n".join(result))

#str형태로 입력값 i를 []에 저장하여 한번에 출력값으로 변환
 

 

  • 이처럼 출력도 “모아서 한 번에” 진행하면 출력속도를 향상할 수 있습니다

5. 실전 템플릿

제가 설명한 모든 방법을 적용한 코딩 테스트 템플릿입니다.

 
import sys
input = sys.stdin.readline  # 또는 os.read 방식 선택

# 전체 입력을 한 번에 읽는 경우
# data = sys.stdin.read().split()
# idx = 0
# def rd(): global idx; idx += 1; return data[idx - 1]

output = []

# --- 알고리즘 코드 ---

print("\n".join(output))

 

========================================================

코딩 테스트에서 Python을 쓴다면 입출력 최적화는 선택이 아니라 기본 세팅입니다.

 

특히 read(). split() + 출력 모아서 한 번에의 조합만으로도 시간 초과 문제의 상당수를 해결할 수 있습니다.

 

이를 통해서 꼭 코딩 테스트 합격, PS문제 해결에 도움이 되면 좋겠습니다.

 

 

 

SMALL