Python: Problems and Solutions (Chapter 7 Files and Exceptions Quiz Game)


We continue to practice programming. After the seventh chapter in the book: Michael Dawson “Programming in Python”, 2014 (Michael Dawson “Python Programming for the Absolute Beginner”, 3rd Edition), where I learned how to work with files, it’s time to move on to practice. Let’s do our homework together!

A short summary of working with files in Python

Open and close a file

open() – open file and give directory path;
open("file", "r", encoding="utf-8") – open file for reading in Unicode encoding.

Access to text files:
"r" – reading;
"w" – write (replace content) / create;
"a" – append at the end of the file / create;
"r+" – read and write;
"w+" – write and read (replace content) / create;
"a+" – appending at the end of the file and reading / creating.

.close() – close the file

Read file

Character by character: .read() method – reading the entire file, i.e. we write "variable.read ()", where the number of characters to be read is indicated in brackets. After each reading, Python leaves a “bookmark” in the place where it has read up to.

Line by line: .readline() method – reading a line of a file, i.e. we write "variable.readline ()", where in brackets you can specify the number of characters to be read from the current line.

From text to a list consisting of lines: the .readlines() method – creating a list from the lines of a file, i.e. we write variable_2="variable.readlines()", and now variable_2 is a list of all lines. By running a line print cycle for each element from the list, you can read the file line by line.

Write text to file

Writing a line to a file: method .write(строка) 

Writing a List of Strings to a File: Method .writelines(список строк)

Data conservation and serialization

Canned files are stored in binary (binary) files:

"rb" – reading;
"wb" – write / replace / create;
"ab" – append at the end / create;
"rb+" – read and write;
"wb+" – write and read / replace / create;
"ab+" – append at the end / create.

Conservation:
pickle.dump(оobject_with_data_for_preservation, file_where_save)

You can preserve lists, dictionaries, tuples, numbers, strings.

Reopen:
pickle.load(file_unpack_from)

Shelf for pickled Data

Open file with canned objects:
shelve.open(file, access mode)

Access modes:
c – read / write / create (default);
n – create file read/write/replace;
r – reading;
w – write.

Checking that the data is written to the shelf file:
файл.sync()

Close shelf file (and make all changes):
файл.close()

unicodeescape error

Wrote code:

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

What to do if an error occurs:
(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated\UXXXXXXXX escape

Here \U in “C:\Users\…” triggers an eight-character Unicode escape code, which in Python has the format "\U000XXXXX". In our code, the \U escape character is followed by the ‘s’ character, which is not allowed.

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

There are two solutions:

  1. Double slash characters: “C:\\Users\\Documents\\Python\\file.txt”
  2. Or prefix the address with r (to get the raw string): r"C:\Users\Documents\Python\file.txt"

io.UnsupportedOperation: not readable error

It is not possible to read the file, because in the code we wrote “w” – for writing only, but we need to write “r” – for reading:

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

Exception Handling

try: – code snippet that can throw an exception (error);
except (тип исключения 1, 2....): – code that is executed if an exception is thrown (error message).

There can be any number of consecutive excepts in one try.

If you specify else after all except, then this will be the code that will be executed if there are no errors.

Exception types:
IOError – input/output error;
IndexError – element not found at specified index;
KeyError – key not found in dictionary;
NameError – name not found;
SyntaxError – syntax error in code;
TypeError – operation/function applied to the wrong object;
ValueError – function / operation argument has an invalid value;
ZeroDivisionError – in the operation of division / finding the remainder, the second argument is zero.

An exception argument in Python is text that describes the error in the interpreter; it can be output to a variable via as:
try:
...
except an exception as переменная:
...

Game “Quiz”

To complete the task of modifying the game “Quiz”, first take the source code and disassemble the program in parts to better understand the meaning of what is happening.

At the beginning of the code, we specify the global variables in the main() function:

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)

Function that greets the player:

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

The function of opening a file with questions and handling exceptions:

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

A function that takes a file and extracts the following line of text from it:

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

The function that gets the next block of lines corresponding to one question – accepts a file and returns 4 + 4 lines (we divide the text into questions and possible answers).

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

The program asks players questions:

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])

We accept the player’s response:

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

Check if the answer is correct or not:

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

Let’s move on to the next question:

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

When the questions are over, print the ending and the player’s score:

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

Running the main function: main()

Exit the game: input('Нажмите Entr, чтобы выйти')

Task 1. Add the face value of the question

Modify the game so that each question has a “value” – a unique number of points. At the end of the game, the sum of the user’s points must become equal to the sum of the face values of the questions to which he answered correctly.

Solution: add a line to the file with unique values ​​of denominations after the correct answer. And in the code of the function def next_block(the_file): we enter the nominal variable:

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

And in the main() function, we enter calls to 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)

Task 2: Conservation of records

Modify the game “Quiz” so that it stores a list of high scores in a file. The list must include the name and result of the record-breaking player. Use canned objects to store the high score table.

Solution: Add a high_score() function to save the player’s name and score to a file using pickle, and also to output this information. Enter the .dat file (the data was saved in it). In the main () function of the game, we add this function to display the player’s score if he is on the list.

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

Next, in the same function, add the input of the player’s name:

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

Next, in the same function, add overwriting the file:

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

Add option to show results:

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

Task 3: Save to .txt

Implement the same functionality as in the previous task, in a different way: this time, save the list of high scores in a plain text file.

Solution: instead of f = open(“file.dat”) use f = open(“file.txt”)


This entry was posted in Python (en). Bookmark the permalink.

Leave a Reply

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