05의 개발 계발

[TIL] 230329 [Python] threading 모듈, Timer 사용 본문

TIL

[TIL] 230329 [Python] threading 모듈, Timer 사용

생각하는 코댕이 2023. 3. 30. 02:33
728x90

TIL 학습목표

  • threading 모듈, Timer 기능을 사용할 수 있다.
  • 반복문에서 사용 불가한 threading 모듈을 어떻게 활용할지 궁리할 수 있다.

1) 문제점 (Problem)

timelimit = Timer(time_, gameover)  # 5초 후 gamerover 함수 동작

def battle():
    status()
    # 플레이어와 몬스터가 모두 살아있다면 계속 전투, 타임오버가 아니라면 계속 전투
    while player.hp > 0 and random_monster.hp > 0 and play:
        # 전투 시 입력이 5초 내로 없으면 게임종료
        timelimit.start()
        # 동작을 입력받는다
        action = msvcrt.getch()
        # 입력이 있다면 타이머 취소
        timelimit.cancel()

threading 모듈의 Timer 를 사용하여 입력 시간제한을 주고자 위와 같이 코딩을 하였다.

하지만 아래와 같이 오류가 발생했다.

threads는 한번만 실행되어야한다.즉, 반복문 내에서 threads 를 사용할 수 없다는 에러였다.

while문 에서 threads를 사용할 수 없다는 error가 아닌 점에 착안해서,
아예 불가능한 것이 아니라, 나의 사용법이 문제라 생각하고 방법을 찾아보았다.

RuntimeError: threads can only be started once

2) 시도해본 것들 (Try)

▶타이머(timelimit)가 여러번 실행되는지 코딩 분석

 

    # 플레이어와 몬스터가 모두 살아있다면 계속 전투, 타임오버가 아니라면 계속 전투
    while player.hp > 0 and random_monster.hp > 0 and play:
        # 전투 시 입력이 5초 내로 없으면 게임종료
        timelimit.start()
        # 동작을 입력받는다
        action = msvcrt.getch()
        time.sleep(0.1)  # 연속입력 방지
        # 타임오버라면 반복문 빠져나가기
        if not play:
            break
        
        os.system("cls")
        status()
        # 동작을 입력 했다면 타이머 취소 
        timelimit.cancel()
        
        if not action in [b"1", b"2", b"3", b"4", b"5"]:
            print("\n정신차리세요! 용사님!")
            continue
        player.action_choice(random_monster, action)

        random_monster.attack(player)

    if player.hp <= 0:
        print(f"\n{player.name}님은 한줌의 먼지가 되었습니다.")
    # 몬스터가 죽었다면 경험치를1 올린다.
    elif random_monster.hp <= 0:
        player.ex += 1
        print(f"\n{random_monster.name}이(가) 쓰러졌습니다.")

while문 안에서 시작 timelimit.start() 과 취소 timelimit.start() 가 함께 일어나므로 문제가 없다고 판단했다.


▶GPT에게 물어보기

Chat GPT에게 while 구문에서 Timer를 사용하는 방법을 물어보았다.

GPT의 답변

답변과 나의 코드를 비교해 보았더니, 차이점이 하나 보였다.

while 루프 안에서 Timer 객체를 생성해야한다...!


3) 해결 (Solution)

While 문 내부에서 Timer 객체를 생성하고 실행

 while player.hp > 0 and random_monster.hp > 0 and play:
        # 전투 시 입력이 5초 내로 없으면 게임종료
        timelimit = Timer(time_, gameover)  # while 문 내에서 정의하면 timer사용가능!
        timelimit.start()

전역변수로 사용하기 위해 while문 밖에서 생성했던 Timer 객체를, while문 내부에서 정의하고 실행해 보았더니 오류없이 잘 작동되었다.


4) 알게 된 점  (Learnd)

threading 모듈을 반복문에서 사용할 경우, 중복사용되는 오류를 막기 위해서는 객체의 생성과 실행,중지 모두 같은 반복문 내에서 이루어져야한다.

728x90