๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Lect & Tip/Python

ํŒŒ์ด์ฌ RuntimeError: lost sys.stdin ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

by st๊ณต๊ฐ„ 2025. 4. 26.
๋ฐ˜์‘ํ˜•

ํŒŒ์ด์ฌ RuntimeError: lost sys.stdin ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

Traceback (most recent call last):
  File "calculate_daily_tax.py", line 41, in <module>
  File "calculate_daily_tax.py", line 27, in main
RuntimeError: lost sys.stdin

์•„๋ž˜ ์—๋Ÿฌ๋Š” ์ฃผ๋กœ PyInstaller๋กœ --noconsole (๋˜๋Š” --windowed) ์˜ต์…˜์„ ๊ฑธ์–ด์„œ ์ฝ˜์†” ์ž…์ถœ๋ ฅ์ด ๋ง‰ํ˜”๊ฑฐ๋‚˜, ํ˜น์€ IDE ๋‚ด์žฅ ํ„ฐ๋ฏธ๋„ ๋“ฑ์—์„œ sys.stdin์ด ๋‹ซํ˜€ ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

RuntimeError: lost sys.stdin

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.


1. ์ฝ˜์†” ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜์—ฌ exe ๋นŒ๋“œํ•˜๊ธฐ

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์ฝ˜์†” ์ž…์ถœ๋ ฅ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก exe๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

# --noconsole ์˜ต์…˜์„ ์“ฐ์ง€ ์•Š๊ณ , ๊ธฐ๋ณธ ์ฝ˜์†” ๋ชจ๋“œ๋กœ ๋นŒ๋“œ
pyinstaller --onefile tax_calculator.py

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด exe ์‹คํ–‰ ์‹œ input()์ด ์ •์ƒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


2. ์ฝ”๋“œ ๋‚ด์—์„œ stdin์„ ๋ณต๊ตฌํ•˜๋„๋ก ์ˆ˜์ •ํ•˜๊ธฐ

๋งŒ์•ฝ GUI ํ”„๋กœ๊ทธ๋žจ๊ณผ ๊ฐ™์ด ์ฝ˜์†”์ด ์—†๋Š” ํ™˜๊ฒฝ์—์„œ๋„ ์ž…๋ ฅ์„ ๋ฐ›์•„์•ผ ํ•œ๋‹ค๋ฉด, input()์„ ์ง์ ‘ ๊ฐ์‹ธ์„œ sys.stdin์„ ์—ด์–ด ์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ์€ safe_input() ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด, lost sys.stdin ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Windows ์ฝ˜์†” ํ•ธ๋“ค(CONIN$)์„ ๋‹ค์‹œ ์—ฌ๋Š” ๋ฐฉ์‹์˜ ์ƒ˜ํ”Œ์ž…๋‹ˆ๋‹ค.

#!/usr/bin/env python3
# filename: tax_calculator_safe.py

import sys
import os

def ensure_stdin():
    """
    sys.stdin์ด ๋‹ซํ˜”๊ฑฐ๋‚˜ ์†์‹ค๋œ ๊ฒฝ์šฐ,
    Windows์˜ CONIN$๋ฅผ ํ†ตํ•ด ์ฝ˜์†” ์ž…๋ ฅ์„ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค.
    """
    try:
        if sys.stdin is None or sys.stdin.closed:
            # Windows ์ „์šฉ: ์ฝ˜์†” ํ•ธ๋“ค์„ ์—ด์–ด stdin์„ ๋ณต๊ตฌ
            sys.stdin = open('CONIN$', 'r')
    except Exception:
        pass

def safe_input(prompt: str) -> str:
    """
    input() ํ˜ธ์ถœ ์‹œ RuntimeError: lost sys.stdin ๋ฐœ์ƒํ•˜๋ฉด
    stdin์„ ๋ณต๊ตฌํ•˜๊ณ  ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
    """
    try:
        return input(prompt)
    except RuntimeError as e:
        if 'lost sys.stdin' in str(e):
            ensure_stdin()
            return input(prompt)
        raise

def calculate_daily_tax(daily_wage, work_days):
    gross     = daily_wage * work_days
    deduction = 150_000 * work_days
    taxable   = max(gross - deduction, 0)      # ๊ณผ์„ธ์†Œ๋“
    basic_tax = taxable * 0.06                 # ์‚ฐ์ถœ์„ธ์•ก
    reduced   = basic_tax * (1 - 0.55)         # ๊ฒฐ์ •์„ธ์•ก
    final_tax = reduced * 1.1                  # ์ง€๋ฐฉ์†Œ๋“์„ธ ํฌํ•จ
    return round(final_tax)

def main():
    print("=== ์ผ์šฉ์ง ์†Œ๋“์„ธ ๊ณ„์‚ฐ๊ธฐ (Safe Mode) ===")
    try:
        daily = int(safe_input("1. ์ผ๊ธ‰์—ฌ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”(์›): ").replace(',', ''))
        days  = int(safe_input("2. ๊ทผ๋ฌด์ผ์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”(์ผ): "))
    except ValueError:
        print("โ–ถ ์˜ฌ๋ฐ”๋ฅธ ์ˆซ์ž๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
        return

    tax = calculate_daily_tax(daily, days)
    print("\n--- ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ---")
    print(f"์ด ๊ธ‰์—ฌ์•ก    : {daily * days:,}์›")
    print(f"์›์ฒœ์ง•์ˆ˜์„ธ์•ก : {tax:,}์›")
    print("โ€ป ์„ธ์•ก์ด 1,000์› ๋ฏธ๋งŒ์ด๋ฉด ์ง•์ˆ˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")

if __name__ == "__main__":
    main()

์œ„ ์Šคํฌ๋ฆฝํŠธ๋ฅผ tax_calculator_safe.py๋กœ ์ €์žฅํ•œ ๋’ค, ์•„๋ž˜์™€ ๊ฐ™์ด exe๋กœ ๋นŒ๋“œํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

pyinstaller --onefile --name ์ผ์šฉ์ง์„ธ๊ธˆ๊ณ„์‚ฐ๊ธฐ_safe tax_calculator_safe.py
  • --onefile: ๋‹จ์ผ exe
  • --name: exe ํŒŒ์ผ๋ช… ์ง€์ •
  • (๊ธฐ๋ณธ): ์ฝ˜์†” ์ฐฝ์ด ์ž๋™์œผ๋กœ ์—ด๋ ค input()์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์š”์•ฝ

  • ๊ฐ„๋‹จํžˆ: --noconsole ์˜ต์…˜์„ ๋นผ๊ณ  ์ฝ˜์†” ๋ชจ๋“œ๋กœ ๋นŒ๋“œํ•˜๋ฉด RuntimeError: lost sys.stdin ๋ฌธ์ œ๊ฐ€ ์—†์–ด์ง‘๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ ์ˆ˜์ •: safe_input()์ฒ˜๋Ÿผ RuntimeError๋ฅผ ์žก์•„์„œ sys.stdin์„ ๋ณต๊ตฌํ•˜๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋ฉด, ์ฝ˜์†” ์—†๋Š” ํ™˜๊ฒฝ์—์„œ๋„ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€