在Python中读取文本文件并从中选择类别

时间:2015-10-15 02:05:08

标签: python parsing python-3.x exception recursion

您好我是一名非常新的程序员,他自学Python。我遇到了一个非常有趣的问题,需要一些帮助来为它创建一个程序。它就像这样

酒店销售人员在文本文件中输入销售。每行包含以下内容,以分号分隔:客户的名称,销售的服务(如晚餐,会议,住宿等),销售金额以及该事件的日期。编写一个读取此类文件的程序,并显示每个服务类别的总金额。如果文件不存在或格式不正确,则显示错误。

  • 提示要处理和发出的文件的名称 错误消息,如果无法打开该文件则终止

  • 验证每一行的项目数是否正确   如果不是

  • 则终止
  • 验证美元金额是否为有效浮点数      数字,如果不是

  • 则终止
  • 保持列表中包含遇到的类别(他们         可能与下面不同)和另一个列表         每个类别的累计美元金额。这是两个         列表,但一个元素与中的元素相关         另一个(按位置)

  • 处理完所有数据后关闭文件

  • 显示每个类别和总数

我们的示例文本文件看起来像这样

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

这是我的代码。我在main()收到缩进错误。有人可以帮助纠正我的代码并根据问题完善它吗?如果需要,请随时删除整个代码。

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()

使用上述正确文件运行的输出应为:

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

Totals:
Dinner: $  24.00

Lodging: $ 250.00

4 个答案:

答案 0 :(得分:1)

我发现你花了相当多的时间,但我认为最好使用手头的工具。

为了提高效率,我知道在您学习的过程中,这并不是您所需要的100%,但将数据导入pandas可以节省大量时间。

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

为了记住这一点,虽然你可以在不使用额外软件包的情况下做任何事情,但是他们出于某种原因并且拥有合适的工具可以让工作变得更轻松。 假设这不是一个家庭作业问题

答案 1 :(得分:1)

使用包含以下内容的文本文件

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

我做了一些小改动,得到了你想要的输出:

Totals:
Dinner: $ 24.0
Lodging: $ 250.0

我遇到了很多与原始代码相关的问题。 amount_by_category拼写错误。 try中的process_file需要except。在阅读文件时,它实际上是在跳过第一行,因此永远不会处理Bob。那是因为你读了一行,然后对它做了什么并进入循环。 0.0f不是浮点数,只需0.0正确投射即可。

您还应该考虑停止使用try except作为拐杖。这是一种非常懒惰的编程方式,而不是实际修复错误。在这种情况下,如果您需要输入,则可以轻松检查文件,因此不需要使用try

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()

希望有所帮助。

答案 2 :(得分:0)

您收到语法错误,因为您的号码后面不能使用字母'f'。 在python中,您可以使用小数点或使用内置类型float()

来获取浮点数。

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

所有将产生相同的结果

答案 3 :(得分:0)

我不知道您是否正在寻找特定的python3.x答案,但我复制粘贴您的代码并做了一些小改动。
对于3.1, raw_input 应更改为输入 我希望它有所帮助。

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