0

How do i get a function to read a certain amount of lines and then compute a total by adding up the numbers from those lines printing it then looping to read the next lines etc. The function opens up a file that has hundreds of lines with numbers on them.

Example:

def open_input_file():
    while True:
        name_of_file = input("Enter the name of the input file: ")
        try:
            file_wanted = open(name_of_file, 'r')
            return file_wanted
        except FileNotFoundError:
            print(f"The file {name_of_file} was not found. Check the file name and try again.")


def average_steps(read_file, amount_of_days):
    open(read_file.name, 'r')
    amount_of_lines = len(open(read_file.name).readlines(amount_of_days))

    total = 0
    for line in read_file:
        num = int(line)
        total += num

    average = total / amount_of_lines
    return average


def main():
    file_wanted = open_input_file()
    month_list = ['January', 'February', 'March', 'April',
                  'May', 'June', 'July', 'August', 'September',
                  'October', 'November', 'December']
    day_list = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    day_being_used = 0
    month_being_used = 0
    months = 12

    for month_being_used in range(months):
        steps = average_steps(file_wanted, day_list[day_being_used])
        print(f"The average steps taken in {month_list[month_being_used]} was {steps} ")
        day_being_used += 1
        month_being_used += 1
    file_wanted.close()

if __name__ == '__main__':
    main()
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Oct 25 '22 at 07:15

2 Answers2

1
import sys


def open_input_file():

file_wanted = None
while file_wanted is None:
    name_of_file = input("Enter the name of the input file: ")
    try:
        file_wanted = open(name_of_file, 'r', encoding="utf-8")
        return file_wanted
    except FileNotFoundError:
        print(f"The file {name_of_file} was not found. Check the file name and try again.")


def average_steps(file, day):

count = day
total = 0
try:
    for i in range(day):
        line = file.readline()
        num = int(line)
        total += num
    average = total / count
    return average
except ValueError:
    print("The program has aborted because the steps file contains invalid data.")
    print("The error is: invalid literal for int() with base 10: ''")
    sys.exit(1)


def main():

file_object = open_input_file()
month_list = ['January', 'February', 'March', 'April',
              'May', 'June', 'July', 'August', 'September',
              'October', 'November', 'December']
day_list = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

day_being_used = 0

for month_being_used in range(len(month_list)):
    avg_steps = average_steps(file_object, day_list[day_being_used])

    print(f"The average steps taken in {month_list[month_being_used]} was {avg_steps: 7,.0f} ")
    day_being_used += 1
    month_being_used += 1

file_object.close()

if name == 'main': main()

0

I feel it simplifies some of the logic if we just read the whole file into a list using list comprehension. It also seemed like you were opening the file 3 times in the code(or 25 times if we count each time it's opened in the loop). Once should be enough.

Once you have the data in a list, it's possible to just take slices of the list for each month. With a list you can also use python functions like sum() and len() to handle the average calculation.

I put the following online here with 'nums' as the file full of numbers.

def open_input_file():
    while True:
        name_of_file = input("Enter the name of the input file: ")
        try:
            file_wanted = open(name_of_file, 'r')
            return file_wanted
        except FileNotFoundError:
            print(f"The file {name_of_file} was not found. Check the file name and try again.")




def main():
    file_wanted = open_input_file()
    month_list = ['January', 'February', 'March', 'April',
                  'May', 'June', 'July', 'August', 'September',
                  'October', 'November', 'December']
    day_list = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    day_being_used = 0
    month_being_used = 0

    # The file was already opened. Let's read all lines into a list.
    all_daily_steps = [int(line) for line in file_wanted]
    
    for month_being_used in range(len(month_list)):
        
        # For each month we'll create a new list from all_daily_steps. 
        # The new list will start after the sum of days in all previous months. Ex. The March list would start at the 59th element in the all_daily_steps list (31+28=59)
        list_slice_start = sum(day_list[:month_being_used])

        # It ends after that sum plus the days in the current month
        list_sclice_end = list_slice_start + day_list[day_being_used]

        # Now we're ready to make our new list for the current month 
        current_month_list_slice = all_daily_steps[list_slice_start : list_sclice_end]

        # Sum all the step values in the list divided by the number of of values
        avg_steps = sum(current_month_list_slice)/len(current_month_list_slice)
        
        print(f"The average steps taken in {month_list[month_being_used]} was {avg_steps}")
        day_being_used += 1
        month_being_used += 1
        
    file_wanted.close()

if __name__ == '__main__':
    main()

The tricky thing with defining the days_list is that pesky leap year business. The Datetime library could probably help you out here if we knew the year being referenced. The calendar library is also useful for working with month names.

shawn caza
  • 342
  • 2
  • 13
  • Your solution worked perfectly. But is there a way to have a function called def average in there that accepts the file name and the day/ amount of lines wanted to be read. Like have the program do the same thing but it would have a main, open_input_file, and average_steps(file_name, days) function – Learning_How_To_Code Oct 28 '22 at 15:48
  • "day/ amount of lines wanted to be read" You mean the number of days in each month? Does it always read all the days in a whole year anyway? Or do you want to be able to tell it to read an arbitrary number of days? Like just the first 6 months of the year? Is this a school assignment where you're required to pass only (file_name, days) to the average steps function? That changes a lot. If it's really file name that we need to pass, and not the opened file, then we'd have to call the open file function inside the average steps function. – shawn caza Oct 29 '22 at 12:36
  • 1
    I figured it out. Thank you so much for your help! – Learning_How_To_Code Oct 31 '22 at 06:24
  • Glad you were able to solve the problem! How did you do it? – shawn caza Oct 31 '22 at 12:59
  • I posted the answer above. – Learning_How_To_Code Nov 01 '22 at 22:56