KButler
KButler

Reputation: 97

Reading data from a txt file from string line

I need to write a program to read data stored in a txt file. EX:

3147 R 1000
2168 R 6002
5984 B 2000
7086 B 8002

The first number is an "account number" the "R" is a residential classification, and the last number is "gallons used". I need to produce a program to print this:

Account Number: 3147 Water charge: $5.0

I need to have the code read 4 lines in the text. Residential customers pay $.005 per gallon for first 6000. If higher $.007. Business customers pay $.006 per gallon for first 8000. If higher, $.008 I need to display the product of each 4 lines. The code below is what I tried. I may be way off.

I've tried the code below:

def main():
    input_file = open('C:\Python Projects\Project 
1\water.txt', 'r')
    empty_str = ''
    line = input_file.readline()

    while line != empty_str:

        account_number = int(line[0:4])
        gallons = float(line[7:11])
        business_type = line[5]
        while business_type == 'b' or 'B':
            if gallons > 8000:
                water_charge = gallons * .008
            else:
                water_charge = gallons * .006
        while business_type == 'r' or 'R':
            if gallons > 6000:
                water_charge = gallons * .007
            else:
                water_charge = gallons * .005

        print("Account number:", account_number, "Water 
 charge:$", water_charge)
        line = input_file.readline()

    input_file.close()
main()

It just runs without printing anything

Upvotes: 0

Views: 95

Answers (2)

C.Nivs
C.Nivs

Reputation: 13126

The main problem is that your while loops should be simply if statements:

        if business_type.lower() == 'b':
            if gallons > 8000:
                water_charge = gallons * .008
            else:
                water_charge = gallons * .006

        elif business_type.lower() == 'r':
            if gallons > 6000:
                water_charge = gallons * .007
            else:
                water_charge = gallons * .005

        else:
            # So you don't get a NameError for no water_charge
            water_charge = 0

The reason your while loops never terminate is two reasons: You never read the next line inside that inner loop, and a populated string like 'b' will evaluate like True:

# Strings with content act like True
if 'b':
    print(True)
# True

# empty strings act as False
if not '':
    print(False)
# False

The str.lower() will lowercase the string, so 'R'.lower() returns 'r'. Otherwise there is no break condition for the while and it will spin forever.

Some other suggestions:

1) When opening files, using with eliminates the need to explicitly open and close files:

with open('somefile.txt', 'r') as fh:
    # Everything else goes under the with statement

2) Explicitly calling fh.readline() isn't necessary, as you can iterate over an open file directly:

with open('somefile.txt', 'r') as fh:
    for line in fh:
        # line is the string returned by fh.readline()

This will also terminate when fh is empty, or you reach the end of the file, you might not get explicitly '' when the file is empty, and you no longer need the while loop

3) It's generally bad practice (but also hard to maintain) magic-number code. For instance, what if the account number doesn't have exactly 5 characters? A more succinct way to do this would be with str.split(' '), which will split on spaces:

with open('somefile.txt', 'r') as fh:
    for line in fh:
        # This will split on spaces returning a list
        # ['3147', 'R', '1000'] which can be unpacked into
        # the three variables like below
        account_number, business_type, gallons = line.split(' ')

        # rest of your code here

In total:


# use with for clean file handling
with open('somefile.txt', 'r') as fh:

    # iterate over the file directly
    for line in fh:
        # split and unpack
        account_number, business_type, gallons = line.split(' ')

        # enforce types
        gallons = float(gallons)

        # .strip() will remove any hanging whitespace, just a precaution
        if business_type.strip().lower() == 'b':
            if gallons > 8000:
                water_charge = gallons * .008
            else:
                water_charge = gallons * .006

        elif business_type.strip().lower() == 'r':
            if gallons > 6000:
                water_charge = gallons * .007
            else:
                water_charge = gallons * .005
        else:
            water_charge = 0.0

        print("Account number:", account_number, "Water charge:$", water_charge)


Upvotes: 1

Joe D
Joe D

Reputation: 79

Two things. The reason nothing is appearing is because you are stuck in an infinite loop in the while loop that checks the business type. Changing that to an if statement fixes it.

In addition, when you use and, or, or some other operator, you have to specify the variable again you are comparing.

Your while statement that reads the lines of the file should look like this:

while line != empty_str:

    account_number = int(line[0:4])
    gallons = float(line[7:11])
    business_type = line[5]
    if business_type == 'b' or business_type =='B':
        if gallons > 8000:
            water_charge = gallons * .008
        else:
            water_charge = gallons * .006
    if business_type == 'r' or business_type =='R':
        if gallons > 6000:
            water_charge = gallons * .007
        else:
            water_charge = gallons * .005

    print("Account number:", account_number, "Water charge:$", water_charge)
    line = input_file.readline()

Output:

('Account number:', 3147, 'Water charge:$', 5.0)

Upvotes: 1

Related Questions