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