C++
'Progress bar는 어떻게 작동하는 가?' 를 생각해 보면 좋다.
[==> ] 9/100
[===> ] 10/100
보통 위와 같이 표현되는 데, 실제로 줄이 계속 새로 출력되는 것이 아니라
같은 줄을 덮어쓰면서 출력된다.
이를 위해 사용하는 문자가 \r(Carriage Return) 이다.
\r은 커서를 현재 줄의 맨 앞으로 이동시키며, 이후 출력되는 문자열이 기존 내용을 덮어쓰게 된다.
void printProgress(int current, int total) {
constexpr int width = 40;
double ratio = static_cast<double>(current) / static_cast<double>(total);
int filled = static_cast<int>(ratio * width);
std::cout << "\r[";
for (int i = 0; i < width; ++i) {
std::cout << (i < filled ? "=" : " ");
}
std::cout << "] "
<< static_cast<int>(ratio * 100.0)
<< "% "
<< current << "/" << total
<< std::flush;
}
여기서 중요한 부분은,
std::cout << "\r[";
이다.
\r을 통해 커서를 맨 앞으로 이동시키고,
새로운 진행 상태를 덮어씌운다.
그리고 마지막
std::flush
로 출력 버퍼를 비워 화면에 반영한다.
Python
Python에서도 동일한 방식으로 Progress bar를 직접 구현할 수 있다.
import time
total = 100
for i in range(total + 1):
ratio = i / total
width = 30
filled = int(ratio * width)
bar = "#" * filled + "-" * (width - filled)
print(f"\r[{bar}] {ratio:.0%}", end="")
time.sleep(0.05)
print("\nDone!")
Python 역시 \r을 이용해 같은 줄을 갱신하는 방식으로 동작한다.
다만 실제 프로젝트에서는 직접 구현하기보다
tqdm 라이브러리를 사용하는 게 일반적이다.
from tqdm import tqdm
import time
for _ in tqdm(range(100)):
time.sleep(0.05)
tqdm은 진행률, 속도, ETA(예상 남은 시간) 등을 자동으로 계산해 주며,
Jupyter Notebook 환경도 지원한다.