Продолжаем практиковаться в программировании. После седьмой главы в книге: Майкл Доусон “Программируем на 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’, что недопустимо.
Есть два варианта решения:
- Удвоить символы “слэш”: “C:\Users\Documents\Python\file.txt”
- Или перед адресом добавить префикс
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”)