按日期搜索文本文件

时间:2017-12-21 21:58:01

标签: python python-3.x date text

我有这样的代码:

from datetime import datetime
from tabulate import tabulate

def search_projection_date():
    projections = open('projections.txt','r').readlines()
    date = input("Input projection date: ")
    try:
        date = date.strptime(date, "%d.%m.%Y.")
    except:
        print("Date input error!")
        #search_projection_date()
    for i in projections:
        projections = i.strip("\n").split("|")
        if date == projections[2]:
            table = [['Code:',projections[0]],['Hall:',projections[1]],['Date:',projections[2]],['Start time:',projections[3]],['End time:', projections[4]],['Day(s):', projections[5]], ['Movie:', projections[6]], ['Price:', projections[7]]]
            print (tabulate(table))
            #break
    else:
        print("No projection on that date")

和这样的文本文件:

0001|AAA|17.12.2017.|20:30|21:00|sunday|For a few dolars more|150
0002|BBB|17.12.2017.|19:30|21:15|saturday|March on the Drina|300
0003|GGG|19.12.2017.|18:00|19:00|tuesday|A fistful of Dolars|500
0004|GGG|16.12.2017.|21:15|00:00|sunday|The Good, the Bad and the Ugly|350

我尝试按日期搜索电影投影... 如果在输入的日期有投影,它将找到它并打印列表,但在打印该列表之前,它将始终打印“日期输入错误”,并在该列表之后“在该日期没有投影”。 (如果我将break放在if语句中,它将仅打印输入日中的第一个找到的投影,而不是else语句,显而易见的)

问题:如果正确输入日期,如何仅打印没有“日期输入错误”的投影列表。 如果日期正确但没有投影以及如何在正确输入之前询问用户输入,如何仅打印“该日期无投影”?通过这种递归方式,它将始终抛出异常和递归search_projection_date()函数。

1 个答案:

答案 0 :(得分:3)

您的代码存在一大堆重大问题。事实上,他们展示了为什么我们经常听到的一些一般性建议实际上是一个很好的建议。

  1. date = input("Input projection date: ")行创建一个名为date的字符串。 input始终返回一个字符串。 Python中的字符串没有名为strptime的方法。这给我们带来了问题#2:
  2. 您不应该捕获一般异常。您可能希望在TypeError子句中捕获ValueErrorexcept。但是,您收到的错误是AttributeError: 'str' object has no attribute 'strptime'。这是因为您无法调用您想要存在的方法但不能。你的除外行可能应该是except ValueError:
  3. 您的except子句没有任何用处(超出上面列出的问题)。如果字符串格式不正确,则打印消息但仍然继续。您可能希望在raise子句中使用except来进一步传播该异常。幸运的是,你真的希望日期成为一个字符串,这将我们带到问题#4:
  4. 您为什么要尝试将字符串转换为日期开头?您无法比较日期对象和从文件中获得的字符串,并期望它们相等。您想要将字符串与字符串进行比较。如果您考虑过某种验证,那很好,但请使用datetime.strptime并且不要替换原始字符串;如果它没有正确转换,只会引发错误。
  5. 只要循环正常终止(即没有else),for循环中的break子句就会执行。由于您总是遍历所有行,因此您将始终触发else子句。您需要有另一种方法来确定是否找到了匹配项,例如布尔标志或计数器。我将展示一个带计数器的例子,因为它更通用。
  6. 您永远不会关闭输入文件。在这个小例子中不是一个大问题,但可能会导致更大的程序出现重大问题。使用with块而不是原始open
  7. 您遍历文件的方法本身并没有错,但效率很低。您将整个文件加载到内存中,然后遍历这些行。在Python中,文本文件已经可以通过行进行迭代,这样效率更高,因为它一次只能将一行加载到内存中,而且也不会让你处理文件两次。
  8. 结合所有这些,您可以使代码看起来像这样:

    def search_projection_date():
        counter = 0
        with open('projections.txt','r') as projections:
            date = input("Input projection date: ")
        for line in projections:
            projection = line.strip("\n").split("|")
            if date == projection[2]:
                table = [['Code:',projection[0]],
                         ['Hall:',projection[1]],
                         ['Date:',projection[2]],
                         ['Start time:',projection[3]],
                         ['End time:', projection[4]],
                         ['Day(s):', projection[5]],
                         ['Movie:', projection[6]],
                         ['Price:', projection[7]]]
                print(tabulate(table))
                counter += 1
        if not counter:
            print("No projection on that date")
        else:
            print("Found {0} projections on {1}".format(counter, date))
    

    我信任您对tabulate的使用,因为我不熟悉该模块,并且无意安装它。请注意,日期验证是可选的。如果用户输入了无效的字符串,那就是结束:您不需要检查'aaaa'之类的日期,因为他们只会打印No projection on that date。如果您坚持要保留验证,请执行以下操作:

    from datetime import datetime
    
    datetime.strftime(date, '%d.%m.%Y.')
    

    那就是它。如果日期不匹配,它将引发ValueError。你不需要对结果做任何事情。如果要更改错误消息,或者返回而不是引发错误,则可以捕获异常:

    try:
        datetime.strftime(date, '%d.%m.%Y.')
    except ValueError:
        print('Bad date entered')
        return
    

    请注意,我在这里捕获一种非常特殊的异常类型,而不是使用泛型except子句。