Part-3: Crash-Proof Server Log Reader

Build a Python log reader that handles missing files and writes event reports.

Introduction

30 Second Summary

A long text file can hide one important failure among dozens of routine updates. Reading every line by hand makes important details easy to miss.

In this project, you will build a command-line server log reader with Python. It turns a stream of server events into a saved summary with an error total.

What You'll Build

You'll run the finished reader to see each event checked before opening its saved totals in a standard Linux text editor (like nano, vim, or gedit).

By the end of this project, you'll have:

  • Repeated server checks: Run checks across named servers with a for loop. Retry a check three times with a while loop.
  • Crash-proof checks: Reuse one function to inspect server data. See a clear message when server_events.txt is missing.
  • Saved report: Read every event from server_events.txt. Create summary_report.txt with the server total plus the error total.
  • Secret Mission: Count warning events and add the total to summary_report.txt.

Are there any prerequisites?

You need basic familiarity with variables, lists, if checks, and print() from Projects 1 and 2.

A standard Linux environment with Python 3 is required. Step 1 helps you verify Python and prepare a standard Linux text editor (like nano, vim, or gedit).

Before We Start

Before the hands-on work begins, lock in what your log reader will do and why its report matters.

Check the Existing Tools

Your log reader needs a reliable place to run before you add loops or file handling. A quick test confirms that the tools on your computer can create the project without changing Python itself.

In this step, you will prepare a standard Linux text editor (like nano, vim, or gedit). You will use the standard Linux terminal to verify Python 3 and create project3_loops.py as a runnable starting point.

In this step, get ready to:
  • Open a standard Linux text editor and prepare it for Python files.
  • Verify Python 3 in the standard Linux terminal.
  • Create a runnable project3_loops.py file in your text editor.
Open a Linux text editor

A standard Linux text editor gives you a place to write and save the project files. The installed Python 3 interpreter runs the code from the standard Linux terminal.

  • Open the application menu in your standard Linux environment.
  • Search for a standard Linux text editor, such as nano, vim, or gedit.
  • Select the available text editor from the results.
  • Open the editor's settings or preferences if it provides them.
  • Find the language or syntax-highlighting settings.
  • Enable Python syntax highlighting if the editor offers it.
  • Return to the main editor window.

Can't find a text editor?

  • Open the software manager provided by your standard Linux environment.
  • Search for a standard Linux text editor, such as nano, vim, or gedit.
  • Install one of the available editors.

Help me prepare a Linux text editor.

Verify Python 3

The standard Linux terminal lets you run shell commands. The python3 command starts the installed Python 3 interpreter.

  • Open the application menu in your standard Linux environment.
  • Search for terminal and open the standard Linux terminal.
  • Print a readiness message by running this command:
python3 -c "print('Python 3 is ready')"

What does this command check?

  • The python3 command starts the Python 3 interpreter.
  • The -c option tells Python to execute the statement included in the command.
  • The print() call sends the readiness message to the standard Linux terminal.

You will see exactly Python 3 is ready.

Python check not running?

Make sure you typed python3 in lowercase. Check that the quotation marks match the command above.

Help me troubleshoot the Python 3 readiness command.

Create the workspace file

A script is a text file containing Python instructions. Your first script prints one message so you can prove that your text editor saves code Python can run.

  • Create project3_loops.py in the current standard Linux terminal folder and open it in your default text editor by running this command:
touch project3_loops.py && xdg-open project3_loops.py

What does this command do?

The touch command creates project3_loops.py if it does not exist. The xdg-open command opens that file with the default application in your standard Linux environment.

You will see project3_loops.py open in a standard Linux text editor (like nano, vim, or gedit).

File did not open?

Check that the command begins with lowercase touch and includes xdg-open. Confirm that the filename ends with .py.

Help me open the Python file in my Linux text editor.

  • Enter this line in your standard Linux text editor:
print("Project 3 workspace ready")

What does this code do?

The print() function displays the text inside its parentheses. This gives your script one visible result when Python runs it.

  • Save project3_loops.py with your text editor's save command.
  • Return to the standard Linux terminal.

Before you run the script, what message do you expect the standard Linux terminal to print?

  • Run your saved workspace file with this command:
python3 project3_loops.py

What does this command do?

The python3 command runs the instructions saved in project3_loops.py. The output confirms that Python can find the file in the current folder.

You will see exactly Project 3 workspace ready.

That is your first Project 3 success. Python can run the file you saved with your standard Linux text editor.

Do you see different output?

Confirm that VS Code saved the file as project3_loops.py in the current integrated terminal folder. Compare the spelling and quotation marks with the code above.

Help me fix my workspace script.

✔️ Awesome, I've got everything!

Your saved file now matches the starting workspace. VS Code's integrated terminal prints the expected readiness message.

ⓧ I'd like to double check the full code

  • Compare your saved project3_loops.py file with this complete starting code:
print("Project 3 workspace ready")

What should match?

Your file contains one print() call with the exact workspace message. Matching capitalization and quotation marks keeps the check consistent.

Your tools are ready for the project. Next, you will replace the starter line with loops that repeat server checks.

Repeat Server Checks

Your Python workspace is ready. project3_loops.py already runs from XFCE Terminal.

A log reader needs to check several servers without repeating the same instruction by hand.

A for loop visits each server in a list. A while loop repeats while its condition stays true.

In this step, get ready to:
  • Repeat one check across three server names.
  • Repeat a server check three times.
  • Verify the six output lines from one script run.
Repeat checks with a for loop

The servers list holds three names. The loop gives each name to server one at a time.

  • In Xed, select the existing print("Project 3 workspace ready") line in project3_loops.py.
  • Replace the selected line by entering the code below:
servers = ["web-1", "web-2", "db-1"]
for server in servers:
    print("Checking", server)

What does this code do?

  • The servers list keeps the three server names together.
  • The for server in servers: line visits each name in order.
  • The indented print("Checking", server) line prints the current server name.
  • Save project3_loops.py in Xed.
  • Check the new loop by running this command in XFCE Terminal:
python3 project3_loops.py

What does this command do?

The command asks Python 3 to run every instruction currently saved in project3_loops.py.

You'll see three lines: Checking web-1, Checking web-2, and Checking db-1.

How can you reuse this pattern?

The same loop can check cache-1 followed by cache-2. Each server produces one output line.

A loop over 40, 75, and 90 can print three disk values. A loop over INFO, WARN, and ERROR can print three log levels.

🙋‍♀️ Seeing a loop error?

  • Check that for server in servers: ends with a colon.
  • Indent print("Checking", server) with four spaces.

Ask for help with the exact code you saved: Help me fix my Python for loop.

Add a condition-controlled while loop

A condition is a check that is true or false. A counter records how many checks have happened.

Here, attempt <= 3 allows three checks. Updating attempt moves the loop toward its stopping point.

  • Place the cursor on the blank line below print("Checking", server) in project3_loops.py.
  • Add the three-check loop by entering the code below:
attempt = 1
while attempt <= 3:
    print("Server check", attempt)
    attempt = attempt + 1

What does this code do?

  • The attempt = 1 line starts the counter at the first check.
  • The while attempt <= 3: line repeats while the counter is no greater than three.
  • The attempt = attempt + 1 line increases the counter after each check.

💡 How can the counter change?

A two-check limit prints Server check 1 followed by Server check 2.

A counter that starts at 3 and decreases prints Retry in 3 through Retry in 1. An increasing counter can print Health check 1 through Health check 3.

Verify both loop patterns

The script now contains two stopping rules. The first loop finishes after the final server name.

The second loop finishes when attempt <= 3 becomes false.

  • Save project3_loops.py in Xed.

Before you run the script, which loop do you expect to finish first?

  • Verify both loops by running this command in XFCE Terminal:
python3 project3_loops.py

Why does the output follow this order?

Python runs the file from top to bottom. The server loop finishes before Python reaches the attempt counter.

You'll see Checking web-1, Checking web-2, and Checking db-1.

After those lines, you'll see Server check 1, Server check 2, and Server check 3.

You have both loop patterns working now. Your script checks every server before completing three retry-style checks.

Loop not stopping or showing a syntax problem?

  • Check that each loop header ends with :.
  • Indent each loop body with four spaces.
  • Keep attempt = attempt + 1 inside the while loop.
  • Press Ctrl+C in XFCE Terminal if an accidental loop does not stop.

Need another pair of eyes? Help me fix my Python loops.

✔️ Awesome, I've got everything!

Your two loops are working. Double check that you saved project3_loops.py.

ⓧ I'd like to double check the full code

Compare your project3_loops.py file with this complete version:

servers = ["web-1", "web-2", "db-1"]
for server in servers:
    print("Checking", server)

attempt = 1
while attempt <= 3:
    print("Server check", attempt)
    attempt = attempt + 1

How should you use this reference?

Compare each line with your saved file. Pay close attention to the colons and four-space indentation.

Your repeated server checks are working. Next, you'll turn server-checking work into a reusable block.

Build a Reusable Server Check

Your loop script now checks three servers before repeating a numbered check three times. That repetition gives your automation a predictable rhythm.

Copying the same check into every script makes future changes harder. A function gives that work one reusable name.

Reusable work can still depend on a file that is missing. The last test in this step shows how Python reports that situation.

In this step, get ready to:
  • Define a reusable server-check function.
  • Practice parameters, arguments, loops, and return values.
  • Run a file reader against a missing log file.
Create and call a reusable function

The def keyword starts a function definition. A parameter receives a value inside that function.

An argument supplies the value when you call the function. The return keyword sends a result back to the caller.

  • Create project3_functions.py in the current XFCE Terminal folder by running this command:
xed project3_functions.py

What does this command do?

The command asks Xed to open project3_functions.py. Xed starts a new document for that filename when the file does not exist.

  • Build the reusable server check by pasting this code into project3_functions.py:
def check_server(server):
    print("Checking", server)
    return "OK"

result = check_server("web-1")
print("Result:", result)

What does this code do?

  • The check_server(server) function gives the server check a reusable name.
  • The server parameter holds the server name supplied by the caller.
  • The return "OK" line sends a result back after the check runs.
  • The result variable stores the value returned by the call.
  • Save project3_functions.py.

Before you run the script, make a quick prediction about which output line appears first.

  • Test the reusable check in XFCE Terminal by running this command:
python3 project3_functions.py

What does this command test?

Python runs the saved script from top to bottom. The function call performs the check before the final print() displays its returned value.

You should see Checking web-1 first. The final line should be Result: OK.

Great progress. Your server check now accepts a server name before returning a result that the rest of the script can use.

Function not running?

Check that every line inside check_server(server) starts with four spaces. Make sure the call to check_server("web-1") sits below the function definition.

If you only define the function, Python stores the reusable work without running it. The function call triggers the output.

Help me debug my reusable server function.

Practice parameters and return values

These exercises change the shape of the function while keeping the same pattern. Each one defines reusable work before calling it with specific arguments.

Exercise 1: Show disk use.

Use a function named show_disk(percent). A call with 72 needs to print Disk used: 72 %.

  • Replace the current contents of project3_functions.py with your solution.
  • Save project3_functions.py.
  • Rerun the saved script in XFCE Terminal by pressing the Up Arrow key followed by Enter.

You should see Disk used: 72 %.

Exercise 2: Return a server status.

Use a function named server_status(server, status) that returns a sentence. Calling it with db-1 plus online needs to produce db-1 is online when you print the returned value.

  • Replace the current contents of project3_functions.py with your solution.
  • Save project3_functions.py.
  • Rerun the saved script in XFCE Terminal by pressing the Up Arrow key followed by Enter.

You should see db-1 is online.

Exercise 3: Check several servers.

Use a function named check_servers(servers) with a for loop. Call it with the server names web-1 plus db-1.

  • Replace the current contents of project3_functions.py with your solution.
  • Save project3_functions.py.
  • Rerun the saved script in XFCE Terminal by pressing the Up Arrow key followed by Enter.

You should see Checking web-1 on the first line. You should see Checking db-1 on the second line.

Exercises not producing the expected output?

Make sure each function body starts with four spaces. Add the function name with parentheses below its definition so Python calls it.

Check that a function using return has its result passed to print().

Help me check my function exercise.

A function gives reusable work a clear name. Parameters make that work flexible across different values.

  • Restore the reusable server-check example in project3_functions.py by replacing the exercise code with this code:
def check_server(server):
    print("Checking", server)
    return "OK"

result = check_server("web-1")
print("Result:", result)

Why restore this version?

This is the reusable function that belongs in the finished project. Restoring it keeps project3_functions.py focused on one server-check example.

  • Save project3_functions.py.
  • Return to XFCE Terminal.
  • Press the Up Arrow key to recall the previous command.
  • Press Enter to run the restored script.

You should once again see Checking web-1 followed by Result: OK.

✔️ Awesome, I've got everything!

Your exercises are complete. Confirm that project3_functions.py is saved with the reusable server-check example.

ⓧ I'd like to double check the full code

Compare your saved project3_functions.py with this complete version.

def check_server(server):
    print("Checking", server)
    return "OK"

result = check_server("web-1")
print("Result:", result)
Test a missing log file

The open(...) function asks Python to open a file. The with statement makes sure Python closes the file after the block finishes.

An encoding turns stored bytes into text. This reader uses utf-8 for its text file.

  • Create project3_safe_file.py in the current XFCE Terminal folder by running this command:
xed project3_safe_file.py

What does this command do?

Xed opens a document for project3_safe_file.py in the same folder. This keeps the file reader separate from your function exercises.

  • Build the first log-reading version by pasting this code into project3_safe_file.py:
def read_log():
    with open("server_events.txt", encoding="utf-8") as log_file:
        print(log_file.read())

read_log()

What does this code do?

  • The read_log() function holds the file-reading work under one reusable name.
  • The log_file variable represents the opened server_events.txt file.
  • The read() call requests all remaining text from the file.
  • The final read_log() call starts the file-reading work.
  • Save project3_safe_file.py.

Before you run this script, predict whether Python can complete read_log() while server_events.txt is absent.

  • Test the file reader in XFCE Terminal by running this command:
python3 project3_safe_file.py

What does this command test?

Python calls read_log() before asking the operating system for server_events.txt. The result shows how an unhandled file problem travels out of a function.

You should see a traceback with details about where the problem happened. Its final line names FileNotFoundError plus 'server_events.txt'.

This failure is intentional

The traceback proves that Python reached the file-opening line. It also proves that the current function has no response for an absent file.

The local path in the middle of your traceback can differ from other learners' paths. The exception name and missing filename are the stable clues.

🙋‍♀️ No missing-file traceback?

Check the current folder for an existing server_events.txt file. This test depends on that file being absent.

Check that the filename inside open(...) is exactly server_events.txt.

Help me understand my missing-file test.

✔️ Awesome, I've got everything!

Your file reader is saved. You have also observed the intended missing-file traceback.

ⓧ I'd like to double check the full code

Compare your saved project3_safe_file.py with this complete starting version.

def read_log():
    with open("server_events.txt", encoding="utf-8") as log_file:
        print(log_file.read())

read_log()

Your reusable server check works, while your first file reader exposes a real missing-file problem. Next, you will catch that expected exception and replace the traceback with a useful message.

Handle Missing Log Files

The previous lesson exposed an important weakness in project3_safe_file.py. A missing server_events.txt file stopped the whole script with a traceback.

Exception handling gives an expected runtime problem a planned response. In this step, you'll catch only FileNotFoundError. Other bugs remain visible.

In this step, get ready to:
  • Learn how try and except respond to expected problems.
  • Replace the crashing function with a specific missing-file handler.
  • Confirm that the script prints a clear message without a traceback.
Understand targeted exception handling

An exception is a problem Python finds while a script is running. A specific handler responds only to the exception type it names.

How do try and except work?

  • The try block contains code that might encounter an expected problem.
  • The except block provides the response for a matching problem.
  • FileNotFoundError identifies an attempt to open a file that does not exist.
  • A named exception keeps unrelated failures visible for debugging.
  • Match an absent project3_missing_backup.txt file with FileNotFoundError.
  • Match int("full") with ValueError.
  • Match 10 / 0 with ZeroDivisionError.

What Should Clear Responses Say?

  • A missing backup file can produce project3_missing_backup.txt was not found.
  • An invalid disk value can produce Disk value must be a number.
  • Division by zero can produce A server count cannot be divided by zero.
Catch the missing-file exception

The old read_log() function lets the missing file stop the script. The new structure places the file operation inside a protected block.

  • Switch back to project3_safe_file.py in Xed from earlier.
  • Select all of the existing code in the editor pane.
  • Replace the selected code by pasting the code below:
try:
    with open("server_events.txt", encoding="utf-8") as log_file:
        print(log_file.read())
except FileNotFoundError:
    print("server_events.txt was not found.")

What Does This Code Do?

  • try protects the file operation that can fail.
  • with open(...) closes the file safely after the block finishes.
  • except FileNotFoundError catches only the expected missing-file problem.
  • print() replaces the traceback with a useful message.
  • Save project3_safe_file.py.
  • Before you run the script, predict whether the missing file still produces a traceback.
  • Return to XFCE Terminal from earlier.
  • Run the updated script by using this command:
python3 project3_safe_file.py

You'll see exactly server_events.txt was not found. No traceback follows.

You handled the failure cleanly. The script now explains why it cannot read the log.

Still Seeing a Traceback?

Check that try: and except FileNotFoundError: begin at the same indentation level.

Check that the with open("server_events.txt", encoding="utf-8") as log_file: line remains indented below try:.

Help me fix the missing-file handler.

Using a named exception keeps this handler focused. A bare except: can hide problems that need a different fix.

✔️ Awesome, I've got everything!

Your saved project3_safe_file.py file now matches the crash-proof version.

ⓧ I'd like to double check the full code

The complete project3_safe_file.py file is shown below.

try:
    with open("server_events.txt", encoding="utf-8") as log_file:
        print(log_file.read())
except FileNotFoundError:
    print("server_events.txt was not found.")

The missing-file path is safe now. Next, you'll create real server events. You'll then turn them into a report.

Read Logs and Write a Report

Your missing-file script now handles an absent log without crashing. The finished tool still needs real server events to process.

Temporary output disappears after you close the terminal. File handling lets your script load events from one file and preserve useful totals in another.

In this step, get ready to:
  • Write server events to a text file and read them back.
  • Practice replacing and appending file contents.
  • Build a log reader that saves a summary report.
Create and read the event file

A file object connects Python code to an open file. A mode decides whether that file is read, replaced, or extended.

  • Return to XFCE Terminal from earlier.
  • Start the new project3_files.py file in Xed by running this command:
xed project3_files.py

What does this command do?

This sends the project3_files.py file name to Xed. You will use that document for the file-handling example.

🙋‍♀️ Does Xed fail to open the file?

Make sure you entered the command in XFCE Terminal. Check that the file name ends in .py.

Help me open the Python file in Xed.

  • Enter the following code in project3_files.py.
with open("server_events.txt", "w", encoding="utf-8") as log_file:
    log_file.write("INFO web-1 started\nERROR db-1 disk full\n")
    log_file.write("WARN cache-1 response slow\n")

with open("server_events.txt", encoding="utf-8") as log_file:
    print(log_file.read(), end="")

What does this code do?

  • The first with open(...) block uses "w" mode to replace the contents of server_events.txt with three events.
  • The second with open(...) block opens the event file for reading.
  • The read() method loads the saved text so print() can display it.
  • The encoding="utf-8" setting gives both file operations an explicit text encoding.
  • Save project3_files.py in Xed.
  • Return to XFCE Terminal from earlier.

Before you run it, consider which three event lines you expect to see.

  • Create server_events.txt and print its contents by running this command:
python3 project3_files.py

What should I see?

  • You will see INFO web-1 started on the first line.
  • You will see ERROR db-1 disk full on the second line.
  • You will see WARN cache-1 response slow on the third line.

That output proves the script wrote the event file before reading the same contents back.

🙋‍♀️ Do the event lines look wrong?

Check that each \n remains inside its quoted string. Each one starts a new line in the saved file.

Check that both file operations use server_events.txt with the same spelling.

Help me fix the file-writing example.

Practice file modes

The "w" mode replaces old contents. The "a" mode adds new text after the existing contents.

The first exercise stores Disk free: 35 GB in disk_status.txt. Your solution needs to read the saved line back before printing it.

  • Write your disk status solution in project3_files.py.
  • Save project3_files.py in Xed.
  • Test the exercise from XFCE Terminal by running this command:
python3 project3_files.py

What should I see?

You should see Disk free: 35 GB. This confirms that your script wrote the value to disk_status.txt before reading it.

🙋‍♀️ Is the disk status missing?

Check that the reading block appears after the writing block. Check that both blocks use disk_status.txt.

Help me debug the disk status exercise.

The second exercise stores web-1 plus db-1 on separate lines in server_names.txt. A loop then prints each saved server with a Server: prefix.

  • Write your server-name solution in project3_files.py.
  • Save project3_files.py in Xed.
  • Test the exercise from XFCE Terminal by running this command:
python3 project3_files.py

What should I see?

You should see Server: web-1 on the first line. You should see Server: db-1 on the second line.

🙋‍♀️ Does each server print correctly?

Check that the two server names are separated by a newline in server_names.txt.

Check that the loop body is indented beneath the loop line.

Help me debug the server-name loop.

The third exercise writes WARN web-1 slow to alerts.txt. It uses "a" mode to keep that warning when adding WARN db-1 full.

  • Write your alert-appending solution in project3_files.py.
  • Save project3_files.py in Xed.
  • Test the exercise from XFCE Terminal by running this command:
python3 project3_files.py

What should I see?

You should see WARN web-1 slow on the first line. You should see WARN db-1 full on the second line.

🙋‍♀️ Did the first warning disappear?

Check that the second file operation uses "a" mode. Using "w" there replaces the first warning.

Help me fix the alert-appending exercise.

Those three runs show how file modes control what remains on disk.

Keep file work predictable

Use "w" when the new content should replace the old file. Use "a" when earlier content must stay.

Indent every operation that uses an open file beneath its with open(...) line. The indentation keeps that work inside the managed file block.

The exercises changed project3_files.py. Restore the original event-file example so your project keeps the intended lesson artifact.

  • Replace all content in project3_files.py with the following code:
with open("server_events.txt", "w", encoding="utf-8") as log_file:
    log_file.write("INFO web-1 started\nERROR db-1 disk full\n")
    log_file.write("WARN cache-1 response slow\n")

with open("server_events.txt", encoding="utf-8") as log_file:
    print(log_file.read(), end="")

Why restore this version?

This version recreates the three events required by the combined log reader. It also leaves project3_files.py as a focused example of writing and reading one file.

  • Save project3_files.py in Xed.
  • Recreate the three server events by running this command:
python3 project3_files.py

What should I see now?

You should see the original INFO, ERROR, and WARN event lines. The restored script also leaves those lines in server_events.txt.

🙋‍♀️ Are the original events still missing?

Confirm that you replaced the entire exercise solution. Check that you saved project3_files.py before running it.

Help me restore the event-file example.

✔️ Awesome, I've got everything!

Great. Double check that you saved project3_files.py and recreated server_events.txt.

ⓧ I'd like to double check the full code

Your restored project3_files.py should look exactly like this.

with open("server_events.txt", "w", encoding="utf-8") as log_file:
    log_file.write("INFO web-1 started\nERROR db-1 disk full\n")
    log_file.write("WARN cache-1 response slow\n")

with open("server_events.txt", encoding="utf-8") as log_file:
    print(log_file.read(), end="")
Build the crash-proof log reader

The combined reader brings your earlier patterns into one workflow. A reusable function identifies errors while a for loop checks each event.

A while loop controls the three read attempts. The existing exception handling keeps a missing file from crashing the script.

  • Start the new project3_log_reader.py file in Xed by running this command:
xed project3_log_reader.py

What does this command do?

This sends the new script name to Xed. You will build the reader in two runnable chunks.

🙋‍♀️ Does the new script fail to open?

Run the command from the same XFCE Terminal folder that contains server_events.txt.

Help me open the log reader file.

  • Enter the event-checking code in project3_log_reader.py.
def is_error(line):
    return "ERROR" in line

attempt = 1
log_found = False
event_count = 0
error_count = 0

while attempt <= 3:
    print("Reading log, try", attempt)
    try:
        with open("server_events.txt", encoding="utf-8") as log_file:
            for line in log_file:
                print("Checked:", line.strip())
                event_count = event_count + 1
                if is_error(line):
                    error_count = error_count + 1
        log_found = True
        break
    except FileNotFoundError:
        print("server_events.txt was not found.")
        attempt = attempt + 1

How does the reader work?

  • The is_error(line) function returns whether the current event contains ERROR.
  • The counters record the number of visited events plus the number of error events.
  • The while loop allows up to three attempts to open the log.
  • The for loop prints each stripped event before updating the counters.
  • The except FileNotFoundError block prints a clear message before the next attempt.
  • Save project3_log_reader.py in Xed.

Before you run this chunk, consider how many event lines the loop should check.

  • Test the event-reading loop by running this command:
python3 project3_log_reader.py

What should I see?

  • You will see Reading log, try 1 first.
  • You will see Checked: INFO web-1 started next.
  • You will see Checked: ERROR db-1 disk full next.
  • You will see Checked: WARN cache-1 response slow last.

This proves the retry loop opened the file while the event loop visited all three lines.

🙋‍♀️ Does the reader miss an event?

Check that server_events.txt remains in the same folder as project3_log_reader.py.

Check that every line from for line in log_file: through the error counter is indented inside the file block.

Help me debug the event-reading loop.

The reader now knows whether it found the log. A final branch turns the two counters into a saved report.

  • Place your cursor after attempt = attempt + 1 in project3_log_reader.py.
  • Add the following report-writing code below that line:
if log_found:
    report = "Server events: " + str(event_count) + "\n"
    report = report + "Error events: " + str(error_count) + "\n"
    with open("summary_report.txt", "w", encoding="utf-8") as report_file:
        report_file.write(report)
    print("Report written to summary_report.txt")
    print(report, end="")
else:
    print("No report was written.")

How does the report get written?

  • The if log_found: branch builds the report only after the event file opens successfully.
  • The report variable combines the event total with the error total.
  • The report_file file object writes those totals to summary_report.txt.
  • The else branch explains when all three read attempts fail.
  • Save project3_log_reader.py in Xed.

Before you run the finished reader, consider the total number of events plus the number marked as errors.

  • Create the summary report by running this command:
python3 project3_log_reader.py

What should I see?

  • You will see Reading log, try 1.
  • You will see three lines beginning with Checked:.
  • You will see Report written to summary_report.txt.
  • You will see Server events: 3.
  • You will see Error events: 1.

These lines confirm that the reader checked every event before saving both totals.

🙋‍♀️ Does the report command fail?

Check that the if log_found: line begins at the left edge. Check that its report-writing lines are indented beneath it.

Check that summary_report.txt uses "w" mode so each run saves the latest totals.

Help me debug the completed log reader.

  • Open the saved report in Xed by running this command:
xed summary_report.txt

What should the report contain?

Xed should show Server events: 3 on the first line. It should show Error events: 1 on the second line.

The saved file gives you evidence that remains available after the terminal closes.

🙋‍♀️ Does Xed show the wrong totals?

Return to XFCE Terminal to confirm the script printed three checked events. Check that event_count increases inside the for loop.

Check that error_count increases only when is_error(line) returns true.

Help me correct the saved totals.

You have closed the full workflow. Your script now reads events safely, counts errors, and leaves a report behind.

✔️ Awesome, I've got everything!

Excellent work. Double check that project3_log_reader.py is saved and summary_report.txt contains both totals.

ⓧ I'd like to double check the full code

Your completed project3_log_reader.py should look exactly like this.

def is_error(line):
    return "ERROR" in line

attempt = 1
log_found = False
event_count = 0
error_count = 0

while attempt <= 3:
    print("Reading log, try", attempt)
    try:
        with open("server_events.txt", encoding="utf-8") as log_file:
            for line in log_file:
                print("Checked:", line.strip())
                event_count = event_count + 1
                if is_error(line):
                    error_count = error_count + 1
        log_found = True
        break
    except FileNotFoundError:
        print("server_events.txt was not found.")
        attempt = attempt + 1

if log_found:
    report = "Server events: " + str(event_count) + "\n"
    report = report + "Error events: " + str(error_count) + "\n"
    with open("summary_report.txt", "w", encoding="utf-8") as report_file:
        report_file.write(report)
    print("Report written to summary_report.txt")
    print(report, end="")
else:
    print("No report was written.")

Secret mission

Count Warning Events

Your report already counts error events. Extend its classifier so warning events receive their own total. The finished report will surface problems that deserve attention before they become failures.

Clean Up Your Resources

Clean Up Your Resources

Your Project 3 files cost $0 to keep on this computer. Choose whether to keep them, close the apps for now, or delete them.

Resources you used:

  • Five Python script files: project3_loops.py, project3_functions.py, project3_safe_file.py, project3_files.py, and project3_log_reader.py.
  • Local input file server_events.txt with three server events.
  • Local output file summary_report.txt with three event totals.

Keep everything running

No action is needed. Choose this option if you want Project 4 to build on these files.

  • Keep the seven local files in the folder currently shown in XFCE Terminal.
  • Use the files as references when you continue with Project 4.

Pause - I'll come back to this later

Pausing leaves every saved file in place at no cost. You can continue from the same folder later.

  • Close any open Xed windows.
  • Close XFCE Terminal.

Delete - I don't want to use this again

Deleting these files is permanent. The command below targets only the seven Project 3 filenames listed above.

  • Review the seven filenames above to confirm they belong to Project 3.
  • Remove the Project 3 files from the current XFCE Terminal folder by running this command:
rm project3_loops.py project3_functions.py project3_safe_file.py project3_files.py server_events.txt project3_log_reader.py summary_report.txt

What Does This Command Remove?

The command removes only the seven named files from the folder shown in XFCE Terminal. It leaves your installed tools in place.

  • List the remaining contents of the current XFCE Terminal folder by running this command:
ls

What Should I See?

You should no longer see any of the seven Project 3 filenames listed above. Any unrelated files in the folder stay untouched.

🙋‍♀️ Still See a Project 3 File?

  • Check that XFCE Terminal still shows the folder where you created the Project 3 files.

Help me check my cleanup safely.

Nice Work!

Nice Work!

You did it! Your Python log reader now turns server events into a saved report. It also handles a missing input file without crashing.

You've learned how to:

  • Used loops to automate repeated work. A for loop visits each server event. A while loop controls three read attempts.
  • Built reusable functions with parameters. Used return to send results back to the calling code.
  • Added exception handling around file access. Caught FileNotFoundError with except. Read server_events.txt safely through file handling. Wrote the totals to summary_report.txt.
  • Secret Mission: Classified warnings with classify_line(). Added Warning events: 1 to summary_report.txt.

Ready to quiz yourself?