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:UsersDocumentsPythonfile.txt","w",encoding="utf-8")

print(file.read())

 

Что делать если возникает ошибка:

(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncatedUXXXXXXXX escape

 

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

 

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

 

    1. Удвоить символы “слэш”: “C:\Users\Documents\Python\file.txt”

 

    1. Или перед адресом добавить префикс r (чтобы получить необработанную строку): r"C:UsersDocumentsPythonfile.txt"

 

 

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

 

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

 

file=open(r"C:UsersDocumentsPythonfile.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”)