Exercise 7.2 from Python for Informatics:
Write a program to prompt for a file name, and then read through the file and look for lines of the form:
X-DSPAM-Confidence: 0.8475
When you encounter a line that starts with “X-DSPAM-Confidence:” pull apart the line to extract the floating-point number on the line. Count these lines and then compute the total of the spam confidence values from these lines. When you reach the end of the file, print out the average spam confidence.
Enter the file name: mbox.txt Average spam confidence: 0.894128046745 Enter the file name: mbox-short.txt Average spam confidence: 0.750718518519
Test your file on the mbox.txt and mbox-short.txt files.
My code works. It's a bit more forgiving with the amount of decimals on both input and output, but that's as intended.
What I'm not happy about are the ask_file_name
and retrieve_values
functions. The first uses a hacky method of input validation (the Path module seems appropriate here, but that would be overkill), the second uses iteration while it shouldn't. Perhaps a reduce
would be more appropriate, or something different altogether.
This is written in modern Python. Which means it's written in Python 3 (3.5.2 to be exact, Python 3.7.x is incoming) and has plenty of docstrings. It should be up to standards, but I'd like to have that verified.
AverageSpamConfidence.py
#! /usr/bin/env python3
# coding: utf-8
# Sample data from http://www.py4inf.com/code/
import re
def ask_file_name():
"""
Ask user for file name.
Check for FileNotFound & IsADirectory errors.
Keyword arguments:
-
"""
while True:
try:
user_input = input("Enter the file name: ")
# Is the file there and can we open it?
with open(user_input, "r") as test_input:
pass
except FileNotFoundError:
print("Input empty or file does not exist.")
continue
except IsADirectoryError:
print("That's not a directory, not a file.")
continue
else:
return user_input
def find_occurences_in_file(file_name):
"""
Find all occurences in target file.
Keyword arguments:
file_name -- name of (and path to) target file (example: mbox.txt)
"""
with open(file_name, "r") as input_file:
return re.findall(
'X-DSPAM-Confidence: 0.[0-9]+', str(input_file.readlines())
)
def retrieve_values(input_list):
"""
Return relevant values from list.
Keyword arguments:
input_list -- list to results to retrieve values from
"""
return_list = []
for line in input_list:
return_list.append(float(line.split()[-1]))
return return_list
def average(input_list):
"""
Calculate average of list provided.
Keyword arguments:
input_list -- list of numerical values
"""
return sum(input_list) / len(input_list)
def main():
"""
Exercise 7.2 (Python for Informatics, Charles Severance)
Write a program to prompt for a file name,
and then read through the file and look for lines of the form:
X-DSPAM-Confidence: 0.8475
When you encounter a line that starts with “X-DSPAM-Confidence:” pull apart
the line to extract the floating-point number on the line.
Count these lines and then compute the total of the spam confidence values
from these lines. When you reach the end of the file, print out
the average spam confidence.
"""
file_name = ask_file_name()
occurences = find_occurences_in_file(file_name)
values = retrieve_values(occurences)
print(average(values))
if __name__ == '__main__':
main()
except IsADirectoryError:
. It's a directory, not a file. Not neither. \$\endgroup\$ – Mast Jun 2 '19 at 13:49