Python: Задачи и решения (Глава 7. Файлы и исключения. Игра «Викторина»)


Продолжаем практиковаться в программировании. После седьмой главы в книге: Майкл Доусон “Программируем на Python”, 2014 (Michael Dawson “Python Programming for the Absolute Beginner”, 3rd Edition), где я изучила работу с файлами, пора переходить к практике. Сделаем домашнее задание вместе!

Краткий конспект по работе с файлами в Python

Открыть и закрыть файл

open() — открыть файл и сообщить путь к директории;
open("файл", "r", encoding="utf-8") — открыть файл на чтение в кодировке Unicode.

Доступ к текстовым файлам бывает:
"r" — чтение;
"w" — запись (замена содержимого) / создание;
"a" — дозапись в конце файла / создание;
"r+" — чтение и запись;
"w+" — запись и чтение (замена содержимого) / создание;
"a+" — дозапись в конце файла и чтение / создание.

.close() — закрыть файл

Читать файл

Посимвольно: метод .read() — чтение всего файла, т.е. пишем "переменная.read()", где в скобках указывается число символов, которые надо прочитать. После каждого прочтения Python оставляет «закладку» в том месте, докуда дочитал.

Построчно: метод .readline() — чтение строки файла, т.е. пишем "переменная.readline()", где в скобках можно указать число символов, которые надо прочитать из текущей строки.

Из текста в список, состоящий из строк: метод .readlines() — создание из строк файла списка, т.е. пишем переменная_2="переменная.readlines()", и теперь переменная_2 является списком всех строк. Запустив цикл печати строки для каждого элемента из списка — можно провести построчное чтение файла.

Записать текст в файл

Запись строки в файл: метод .write(строка) 

Запись списка строк в файл: метод .writelines(список строк)

Консервация и сериализация данных

Консервированные файлы хранят в бинарный (двоичных) файлах:

"rb" — чтение;
"wb" — запись / замена / создание;
"ab" — дозапись в конце / создание;
"rb+" — чтение и запись;
"wb+" — запись и чтение / замена / создание;
"ab+" — дозапись в конце / создание.

Консервация:
pickle.dump(объект_с_данными_для_консервации, файл_куда_сохранить)

Можно консервировать списки, словари, кортежи, числа, строки.

Расконсервировать:
pickle.load(файл_откуда_расконсервировать)

Полка для консервированных данных

Открыть файл с консервированными объектами:
shelve.open(файл, режим доступа)

Режимы доступа:
c — чтение / запись / создание (по умолчанию);
n — создание файла для чтения и записи / замена;
r — чтение;
w — запись.

Проверка, что данные записаны в файл полки:
файл.sync()

Закрыть файл полки (и внести все изменения):
файл.close()

Ошибка unicodeescape

Написала код:

file=open("C:\Users\Documents\Python\file.txt","w",encoding="utf-8")
print(file.read())

Что делать если возникает ошибка:
(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated\UXXXXXXXX escape

Здесь \U в «C:\Users\…» запускает восьмизначный escape-код Unicode, который в Python имеет формат "\U000XXXXX". В нашем коде за escape-символом \U следует символ ‘s’, что недопустимо. 

Есть два варианта решения:

  1. Удвоить символы «слэш»: «C:\\Users\\Documents\\Python\\file.txt»
  2. Или перед адресом добавить префикс r (чтобы получить необработанную строку): r"C:\Users\Documents\Python\file.txt"

Ошибка io.UnsupportedOperation: not readable

Не получается прочитать файл, так как в коде мы написали «w» — только для записи, а надо написать «r» — для чтения:

file=open(r"C:\Users\Documents\Python\file.txt","r",encoding="utf-8") 
print(file.read())

Обработка исключений

try: — фрагмент кода, который может вызвать исключение (ошибка);
except (тип исключения 1, 2....): — код, который исполняется, если выпало исключение (сообщение при ошибке).

В одном try может быть сколько угодно последовательных except.

Если после всех except указать else, то это будет тот код, который исполнится, если ошибок не будет.

Типы исключений:
IOError — ошибка ввода/вывода;
IndexError — не найден элемент с указанным индексом;
KeyError — в словаре не найден ключ;
NameError — не найдено имя;
SyntaxError — синтаксическая ошибка в коде;
TypeError — операция / функция применяется к неподходящему объекту;
ValueError — аргумент функции / операции имеет неподходящее значение;
ZeroDivisionError — в операции деления / нахождения остатка второй аргумент ноль.

Аргумент исключения в Python — текст, который описывает ошибку в интерпретаторе; его можно вывести в переменную через as:
try:
...
except исключение as переменная:
...

Игра «Викторина»

Чтобы выполнить задание по модификации игры «Викторина», сначала возьмем исходный код и разберем программу по частям, чтобы лучше понять смысл происходящего.

В начале кода укажем глобальные переменные в функции main():

import sys
def main ():
    the_file=open('C:/Users/<user_name>/Documents/Python/trivia.txt','r',encoding='utf-8')
    title=next_line(the_file)
    welcome(title)
    score=0
    category,question,answers,correct,explanation=next_block(the_file)
    while category:
        print(category)
        print (question)
        for i in range(4):
            print('\ t',i+1,'-',answers[i])

        answer=input('Ответ: ')
        if answer == correct:
            print('/nСупер!')
            score+=1
        else:
            print('/nО, нет!')
        print(explanation)
        print('Счет:',score)
        category, question, answers, correct, explanation = next_block(the_file)
        the_file.close()
        print('Вопросики закончились')
        print('Счет: ', score)

Функция, приветствующая игрока:

def welcome(title):
    print('Приветики!')

Функция открытия файла с вопросами и обработки исключений:

file_name='C:/Users/<username>/Documents/Python/trivia.txt'
mode='r'
def open_file (file_name,mode):
    try:
        the_file=open(file_name,mode, encoding='utf-8')
    except IOError as e:
        print('Не получается открыть файл', file_name, 'ошибка', e)
        input('/n/nНажмите Entr, чтобы выйти.')
        sys.exit()
    else:
        return the_file

Функция, которая принимает файл и достает из него следующую строку текста:

def next_line(the_file):
    line=the_file.readline()
    line=line.replace('/','\n')
    return line

Функция, которая достает следующих блок строк, соответствующий одному вопросу — принимает файл и возвращает 4+4 строки (делим текст на вопросы и возможные варианты ответа).

def next_block(the_file):
    category=next_line(the_file)
    question=next_line(the_file)
    answers=[]
    for i in range(4):
        answers.append(next_line(the_file))
    correct=next_line(the_file)
    if correct:
        correct=correct[0]
    explanation=next_line(the_file)
    return category, question, answers, correct, explanation

Программа задает вопросы игрокам:

category,question,answers,correct,explanation=next_block(the_file)
while category:
    print(category)
    print (question)
    for i in range(4):
        print('\ t',i+1,'-',answers[i])

Принимаем ответ игрока:

answer=input('Ответ: ')

Проверяем ответ — правильный или нет:

if answer == correct:
    print('/nСупер!')
    score+=1
else:
    print('/nО, нет!')
print(explanation)
print('Счет:',score)

Переходим дальше к следующему вопросу:

category, question, answers, correct,ArithmeticError explanation = next_block(trivia_files)

Когда вопросы закончились, выводим окончание и счет игрока:

trivia_file.close()
print('Вопросики закончились')
print('Счет: ', score)

Запуск главной функции: main()

Выход из игры: input('Нажмите Entr, чтобы выйти')

Задание 1. Добавить номинал вопроса

Доработайте игру так, чтобы у каждого вопроса появился «номинал» — уникальное количество очков. В конце игры сумма очков пользователя должна стать равной сумме номиналов вопросов, на которые он ответил правильно.

Решение: добавляем строчкой в файл уникальные значения номиналов после правильного ответа. И в коде функции def next_block(the_file): вводим переменную nominal:

def next_block(the_file):
    category=next_line(the_file)
    question=next_line(the_file)
    nominal=0
    answers=[]
    for i in range(4):
        answers.append(next_line(the_file))
    correct=next_line(the_file)
    if correct:
        correct=correct[0]
        nominal=int(next_line(the_file).strip())
    explanation=next_line(the_file)
    return category, question, answers, correct, explanation, nominal

И в функции main() вводим обращения к nominal:

def main ():
    the_file=open('C:/Users/shtuk/Documents/Python/trivia.txt','r',encoding='utf-8')
    title=next_line(the_file)
    welcome(title)
    score=0
    category,question,answers,correct,explanation,nominal=next_block(the_file)
    while category:
        print(category)
        print (question)
        for i in range(4):
            print('\ t',i+1,'-',answers[i])

        answer=input('Ответ: ')
        if answer == correct:
            print('/nСупер!')
            score+=1
        else:
            print('/nО, нет!')
        print(explanation)
        print('Счет:',score)
        category, question, answers, correct, explanation,nominal = next_block(the_file)
        the_file.close()
        print('Вопросики закончились')
        print('Счет: ', score)

Задание 2: Консервация рекордов

Доработайте игру «Викторина» таким образом, чтобы она хранила в файле список рекордов. В список должны попадать имя и результат игрока-рекордсмена. Используйте для хранения таблицы рекордов консервированные объекты.

Решение: Добавляем функцию high_score (), чтобы сохранить имя игрока и его счет в файле при помощи консервации — pickle, а также, чтобы вывести эту информацию. Вводим файл.dat (в него сохранялись данные). В функции main () игры добавляем эту функцию для отображения счета игрока, если он попадает в список.

def store_high_score ():
    try:
        with open("файл.dat", "rb") as f:
            high_scores = pickle.load(f)
    except FileNotFoundError:
        high_scores = []

Далее в этой же функции добавляем ввод имени игрока:

     name = input("Как тебя зовут")
     player_score = int(input("Сколько очков?"))
     vvod = (name, player_score)
     high_scores.append(vvod)
     high_scores.sort(reverse=True)
     high_scores = high_scores[:5]   

Далее в эту же функцию добавляем перезапись файла:

     with open("файл.dat", "wb") as f: pickle.dump(high_scores, f)

Добавить возможность показать результаты:

f = open("файл.dat", "rb")
show_scores = pickle.load(f)
print(show_scores)
f.close()

Задание 3: Сохранить в .txt

Реализуйте ту же самую функциональность, что и в предыдущей задаче, иным способом: на этот раз сохраните список рекордов в обычном текстовом файле.

Решение: вместо f = open(«файл.dat») использовать f = open(«файл.txt»)


Запись опубликована в рубрике Python. Добавьте в закладки постоянную ссылку.

Добавить комментарий

🇬🇧 Attention! Comments with URLs/email are not allowed.
🇷🇺 Комментарии со ссылками/email удаляются автоматически.