11. 텍스트 파일 다루기

chaejm55·2021년 4월 11일
1

디스코드봇

목록 보기
13/18
post-thumbnail

0. 들어가기 전에

텍스트 파일을 사용하여 기록하는 방법을 알아보겠다. 보통 로그 등을 남기는데 파일을 사용하는데, 이번에는 간단하게 이전에 만들었던 가위바위보 게임의 최근 전적을 기록하는데 사용해보겠다. 약간의 파이썬 기초 지식이 필요하다.

1. 저장할 폴더 생성

os 라이브러리로 폴더 중복여부를 확인하고 text 폴더에 전적을 기록하기 위해 유저 이름으로 된 텍스트파일을 생성한다.

import os
def make_dir(directory_name): // 폴더가 없을 시 폴더를 생성합니다
    try:
        if not os.path.exists(directory_name): // 해당 폴더가 없으면
            os.makedirs(directory_name) // 폴더 생성
    except OSError: // 폴더 생성 오류 시 출력
        print('Error: makedirs()')

2. 텍스트 파일 작성

마찬가지로 os 라이브러리로 파일 중복여부를 확인하고 파일을 생성하고 전적을 기록한다.

def add_result(directory_name, user_name, result):
    file_path = directory_name + '/' + user_name + '.txt'
    // with block으로 close() 자동 호출, encoding 미지정 시 한글이 간헐적으로 깨짐
    if os.path.exists(file_path):
        with open(file_path, 'a', encoding='UTF-8') as f: // 파일이 존재 한다면 append 모드로 추가 기록
            f.write(result)
    else:
        with open(file_path, 'w', encoding='UTF-8') as f: // 파일이 없다면 write 모드로 파일 생성 뒤 기록
            f.write(result)

3. 전적 기록하기

가위바위보 코드를 수정해 위의 함수들을 이용하여 전적을 기록하도록 한다.

@bot.command()
async def game(ctx, user: str):
    rps_table = ['가위', '바위', '보']
    bot = random.choice(rps_table)
    result = rps_table.index(user) - rps_table.index(bot)
    if result == 0:
        result_text = f'{user} vs {bot} 비김'
        await ctx.send(f'{user} vs {bot}  비겼습니다.')
    elif result == 1 or result == -2:
        result_text = f'{user} vs {bot} 승리!'
        await ctx.send(f'{user} vs {bot}  유저가 이겼습니다.')
    else:
        result_text = f'{user} vs {bot} 패배...'
        await ctx.send(f'{user} vs {bot}  봇이 이겼습니다.')
        
    directory_name = "game_result"
    make_dir(directory_name) // 폴더 확인 및 생성
    add_result(directory_name, str(ctx.author), result_text) // 전적 기록

4. 전적 보기

이번엔 파일을 read()로 읽어와 전적을 보여준다.

@bot.command(name="전적")
async def game_board(ctx):
    user_name = str(ctx.author)
    file_path = "game_result/" + user_name + ".txt"
    if os.path.exists(file_path):
        with open(file_path, "r", encoding="UTF-8") as f: // read 모드로 전적 읽기
            result = f.read() // 전체 텍스트 파일을 읽음
        await ctx.send(f'{ctx.author}님의 가위바위보 게임 전적입니다.\n==============================\n' + result)
    else: // 전적 파일이 존재하지 않음
        await ctx.send(f'{ctx.author}님의 가위바위보 전적이 존재하지 않습니다.')

5. 발생할 법할 오류

  • OSError
    파일경로에 잘못된 문자가 들어간 경우에 발생한다. 다시 한번 경로를 확인하자.
  • UnicodeDecodeError
    UTF-8로 작성된 파일을 encoding 지정없이 열 때 발생한다. encoding="UTF-8"을 open()에 추가하자.

6. 마무리

파일을 이용하여 명령어의 결과를 저장하는 기능을 만들어봤다. 전적 외에도 로그, 메시지, 유저 행동 들을 기록하면 더욱 유용하게 활용할 수 있을 것이다.

github 전체 코드

time.sleep(259200)
profile
여러가지를 시도하는 학생입니다

0개의 댓글