简体   繁体   中英

Reading a text file in Python and choosing categories from it

Hello I am a very new programmer who is self teaching Python. I have encountered a very interesting problem and need some help in creating a program for it. It goes like this

A hotel salesperson enters sales in a text file. Each line contains the following, separated by semicolons: The name of the client, the service sold (such as Dinner, Conference, Lodging, and so on), the amount of the sale, and the date of that event. Write a program that reads such a file and displays the total amount for each service category. Display an error if the file does not exist or the format is incorrect.

  • Prompt for the name of the file to process and issue an error message and terminate if that file can't be opened

  • Verify that each line has the correct number of items and terminate if it does not

  • Verify that the dollar amount is a valid floating-‐point number and terminate if it is not

  • Keep a list with the categories that are encountered (they may be different than below) and another list with the cumulative dollar amount for each category. These are two lists but the elements in one relate to the elements in the other (by position)

  • Close the file when all the data has been processed

  • Display the categories and the total for each one

Our Sample text file looks something like this

Bob;Dinner;10.00;January 1, 2015
Tom;Dinner;14.00;January 2, 2015
Anne;Lodging;125.00;January 3, 2015
Jerry;Lodging;125.00;January 4, 2015

Here is my code. I am getting indentation error at main() . Can someone please help in correcting my code and perfecting it as per the question? Please feel free to tear down the entire code if needed.

import sys
def main():

    try:
        line = infile.readline()
        for line in infile:
            inputFileName = input("Input file name: ")
            infile = open(inputFileName, "r")
            fields = line.split(";")

            value = float(fields[1])

    except:
        print("Error: The file cannot be opened.")
        sys.exit(1)

    def process_file(file_name):
        infile = open(file_name, 'r')
        # a dictionary mapping category to total amount for that category
        amount_by_category = {}
        try:
            line = infile.readline()
            for line in infile:
                fields = line.split(';')
                if len(fields) != 4:
                    raise Exception('Expected 4 fields but found %s' % len(fields))
                value = float(fields[2])
                category = fields[1]
                if not category in amount_by_category:
                    amount_by_category[category] = 0.0
                amount_by_category[category] += value
            return amount_by_category
main()

Output from running with the above correct file should be:

Enter the name of the file to display: input.txt

Totals:
Dinner: $  24.00

Lodging: $ 250.00

I see that you have spent some considerable amount of time, but I think it's always best to use the tools at hand.

For sake of efficiency, and I understand that it's not 100% what you're looking for as you're learning, but importing the data into pandas is a great time saver.

import pandas as pd

df = pd.read_csv('data.csv', header = None, sep=';')

dinner = df[df[1]=='Dinner'][2].sum() #1 is the "Dinner/Lodge" and 2 is "Cost"

print(dinner)

>>> 24.0

Just to keep it in mind, while you can do anything without the use of additional packages, they're there for a reason and having the right tool makes the job easier. Assuming it's not a homework problem

With a text file containing:

Bob;Dinner;10.00;January 1, 2015
Tom;Dinner;14.00;January 2, 2015
Anne;Lodging;125.00;January 3, 2015
Jerry;Lodging;125.00;January 4, 2015

I made some minimal changes and got the output you're looking for:

Totals:
Dinner: $ 24.0
Lodging: $ 250.0

There was tons of issues I ran into with the original code. amount_by_category was spelled wrongly. try in process_file needed an except . When reading the file, it was actually skipping the first line, so Bob was never being processed. That's because you read a line, then did nothing with it and went into a loop. 0.0f is not a float, just doing 0.0 will cast it properly.

You should also consider to stop using try except as a crutch. It's a very lazy way to program instead of actually fixing the errors. In this case, you can easily check the file if the inputs are what you need, so the use of try is unnecessary.

def main():
    file_name = input("Input file name: ")
    amount_by_category = process_file(file_name)
    if amount_by_category:
        print 'Totals:'
        for key in amount_by_category:
            print '{0}: $ {1}'.format(key, amount_by_category.get(key) )

def process_file(file_name):
    infile = open(file_name, 'r')
    # a dictionary mapping category to total amount for that category
    amount_by_category = {}
    for line in infile:
        fields = line.split(';')
        if len(fields) != 4:
            raise Exception('Expected 4 fields but found %s' % len(fields))
        value = float(fields[2])
        category = fields[1]
        if not category in amount_by_category:
            amount_by_category[category] = 0.0
        amount_by_category[category] += value
    return amount_by_category

main()

Hope that helps.

You are getting a syntax error since you cannot use the letter 'f' after your number. In python you can get a floating number wither by using the decimal point or by using the built-in type float()

float(0) = 0.0 0. = 0.0 0.0 = 0.0

All will yield the same result

I don't know if you are looking for specific python3.x answers or not, but I copy pasted your code and did some minor alterations.
For 3.1, raw_input should be changed to input .
I hope it helps.

import os

def process_file(file_name):
    infile = open(file_name, 'r')
    amount_by_category = {}
    # a dictionary mapping category to total amount for that category

    line = infile.readline()
    for line in infile:
        fields = line.split(';')
        if len(fields) != 4:
            raise Exception('Expected 4 fields but found %s' % len(fields))
        value = float(fields[2])
        category = fields[1]
        if category not in amount_by_category:
            amount_by_category[category] = 0.0
        amount_by_category[category] += value

    return amount_by_category


if __name__== "__main__": 
    filePath = raw_input("Input file name: ")
    if not os.path.exists(filePath):
        raise Exception("File Does not exists: "+filePath)
    dataDict = process_file(filePath)
    for key,value in dataDict.iteritems():
        print key,value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM