【问题标题】:Help with Python loop weirdness?帮助解决 Python 循环的怪异问题?
【发布时间】:2010-10-16 06:05:12
【问题描述】:

我正在学习 Python 作为我的第二种编程语言(如果不计算 HTML/CSS/Javascript,我将学习第一种真正的编程语言)。我正在尝试构建一些有用的东西作为我的第一个真正的应用程序 - 一个 IRC 机器人,当频道中发生某些事情时,它会通过 SMS 提醒人们。根据某人的请求,我正在(尝试)建立日程安排偏好,人们可以选择在一天中的 X 和 Y 小时之间不接收警报。

无论如何,这是我遇到问题的代码:

db = open("db.csv")
for line in db:
            row = line.split(",")  # storing stuff in a CSV, reading out of it 
            recipient = row[0]     # who the SMS is going to
            s = row[1]             # gets the first hour of the "no alert" time range
            f = row[2]             # gets last hour of above
            nrt = []               # empty array that will store hours
            curtime = time.strftime("%H")  # current hour
            if s == "no":          
                    print "They always want alerts, sending email"  # start time will = "no" if they always want alerts
                    # send mail code goes here
            else:
                    for hour in range(int(s), int(f)): #takes start, end hours, loops through to get hours in between, stores them in the above list 
                            nrt.append(hour)
                    if curtime in nrt: # best way I could find of doing this, probably a better way, like I said I'm new
                            print "They don't want an alert during the current hour, not sending"  # <== what it says
                    else:
                            # they do want an alert during the current hour, send an email
                            # send mail code here

我遇到的唯一问题是脚本最终只能循环通过其中一行(或类似的内容),因为我每次只能得到一个结果,即使我在 CSV 文件中有多个条目.

【问题讨论】:

  • 一般来说,我不会从头开始编写 IRC 机器人,我也会尝试阻止其他人这样做。为 supybot 或 gozerbot 编写插件。
  • 它根本不是一个 IRC 机器人,它所做的只是使用套接字,加入一个房间,并在它看到 x 发生时触发“发送消息”功能。换句话说,我不需要 Supybot 的所有功能。
  • 你确定程序没有失败或抛出异常吗?
  • 是的,它执行成功,没有错误。
  • 为什么不使用现有的 IRC 机器人/框架,为什么不使用 csv 模块?

标签: python csv loops


【解决方案1】:

如果这是一个常规的 CSV 文件,您不应该尝试自己解析它。使用标准库csv module

以下是文档中的一个简短示例:

import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
    print row

【讨论】:

    【解决方案2】:

    您的程序中至少有两个错误:

    curtime = time.strftime("%H")
    ...
    for hour in range(int(s), int(f)):
        nrt.append(hour)
    # this is an inefficient synonym for
    # nrt = range(int(s), int(f))
    
    if curtime in nrt:
        ...
    

    首先,curtime 是一个字符串,而 nrt 是一个整数列表。 Python 是强类型的,因此两者不可互换,并且不会比较相等:

    '4' == 4 # False
    '4' in [3, 4, 5] # False
    

    修改后的代码解决了这个问题,并且比生成列表并在其中搜索当前时间更有效:

    cur_hour = time.localtime().tm_hour
    if int(s) <= cur_hour < int(f):
        # You can "chain" comparison operators in Python
        # so that a op1 b op2 c is equivalent to a op1 b and b op2c
        ...
    

    上面没有解决的第二个问题是,如果时间在午夜左右(例如 s = 22 和 f = 8),您的程序将无法正常运行。

    这些问题都不一定与“脚本最终循环遍历其中一行”有关,但您没有向我们提供足够的信息来弄清楚为什么会这样。一个更有用的提问方式是发布一个简要完整的代码 sn-p 显示您正在观察的行为,以及示例输入和生成的错误消息,如果有的话(连同回溯)。

    【讨论】:

      【解决方案3】:

      您尝试过更简单的方法吗?只是为了看看你的文件是如何被 Python 实际读取的:

      db = open("db.csv")  
      for line in db:  
          print line
      

      您的 csv 文件格式可能存在问题。例如,当您在 Windows 环境中打开 Unix 文件时,就会发生这种情况。在这种情况下,整个文件看起来像单个字符串,因为 Windows 和 Unix 具有不同的行分隔符。所以,我不知道你的问题的某些原因,但提议朝那个方向思考。

      更新: 您有多种方式通过循环体:

      1. s"no" 时:"They always want alerts, sending email" 将被打印。
      2. s 不是"no"curtime in nrt 时:"They don't want an alert during the current hour, not sending" 将被打印。
      3. s 不是"no" 并且curtime in nrt 为假时(最后一个else):什么都不会打印,并且不会执行其他操作。

      您不应该在最后一个else 分支中放置一些print 语句吗?

      另外,你的 sn-p 的确切输出是什么?是"They always want alerts, sending email"吗?

      【讨论】:

      • 两个 sn-ps 是否都以一个结果停止?
      • 不,这个 sn-p 在 CSV 中列出了所有三个结果,但另一个只做一个。
      • 你的 sn-p 的确切输出是什么?是“他们总是想要警报,发送电子邮件”吗?
      • 用代码填写它,它应该执行以下操作:当 s 为否时:当 s != no 和 curtime 在 nrt 时发送警报:当 s != no 并且 curtime 不是时没有警报在 nrt 中:已发送警报
      • 对不起,我不明白你的评论。你期望从你的 sn-p 得到什么结果?如果它们是控制台中的消息,除非 s == "no" (同时考虑 Miles 的回答),否则您将看不到任何消息。
      【解决方案4】:

      我会检查你的条件中的逻辑。您的循环构造应该可以工作。

      【讨论】:

      • 真的很奇怪,我已经逐步完成了 if 语句的流程,它似乎应该可以工作。
      【解决方案5】:

      您可以使用 Python Download 现有的编写良好的 IRC 机器人

      【讨论】:

        【解决方案6】:

        明确说明连续的内容。使用 0, 1, 2...n 实际上是您的错误,它使您或其他人将来很难阅读代码。因此,让我们使用方便的元组来显示我们对一行的期望。这种工作就像代码作为文档

        db = open("db.csv")
        for line in db.readlines():
            recipient, start_hour, end_hour = line.split(",")
            nrt = []
            etc...
        

        这向您的代码的读者展示了您希望一行包含的内容,并且它会在您第一次运行它时向您显示您的错误:)

        【讨论】:

        • for line in db 已经遍历文件的每一行。它在功能上等同于for line in db.readlines(),但内存效率更高,因为它不会将整个文件读入列表中。
        • 啊,我不知道这样迭代的文件,谢谢你的信息。 :)
        猜你喜欢
        • 2022-12-17
        • 1970-01-01
        • 1970-01-01
        • 2011-06-13
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        相关资源
        最近更新 更多