Помогите с странностью петли Python?

1

Я изучаю 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

Единственная проблема, с которой я столкнулась, - это то, что script заканчивается только одним из строк (или что-то в этом роде), потому что я получаю только один результат каждый раз, даже если у меня есть более одной записи в CSV файл.

  • 0
    В общем, я бы не стал писать бот IRC с нуля, и я бы попытался помешать другим сделать это тоже. Напишите плагин для супыбота или гозербота.
  • 0
    Это совсем не IRC-бот, все, что он делает - это использует сокеты, присоединяется к комнате и запускает функцию «отправить сообщение», когда видит, что происходит x. Другими словами, мне не нужны все функциональные возможности Supybot.
Показать ещё 5 комментариев
Теги:
csv
loops

6 ответов

7
Лучший ответ

В вашей программе есть как минимум две ошибки:

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

Ни одна из этих проблем не обязательно связана с "тем, что script заканчивается только зацикливанием по одной из строк", но вы не дали нам достаточной информации, чтобы выяснить, почему это возможно. Более полезный способ задать вопросы - опубликовать короткий, но полный фрагмент кода, который показывает поведение, которое вы наблюдаете, вместе с образцом ввода и результирующими сообщениями об ошибках, если они есть (наряду с трассировкой).

9

Если это обычный CSV файл, вы не должны сами его разбирать. Используйте стандартную библиотеку модуль csv.

Вот краткий пример из документов:

import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
    print row
  • 0
    +1 за не изобретать велосипед :)
5

Вы пробовали что-то более простое? Просто, чтобы увидеть, как ваш файл на самом деле читается Python:

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

Может возникнуть проблема с форматом вашего csv файла. Это происходит, например, при открытии файла Unix в среде Windows. В этом случае весь файл выглядит как одиночная строка, так как Windows и Unix имеют разные разделители строк. Поэтому я не знаю определенной причины вашей проблемы, но предлагаю думать в этом направлении.

Update: У вас есть несколько путей через тело вашего цикла:

  • когда s будет "no": "They always want alerts, sending email" будет напечатано.
  • когда s не "no" и curtime in nrt: "They don't want an alert during the current hour, not sending" будет напечатано.
  • когда s не "no", а curtime in nrt - false (последний else): ничего не будет напечатано и никаких других действий не будет предпринято.

Не следует ли разместить какой-либо оператор print в последней ветке else?

Кроме того, что такое точный вывод вашего фрагмента? Это "They always want alerts, sending email"?

  • 0
    Это хороший способ отладки вашей проблемы.
  • 0
    Нет, это совпадает.
Показать ещё 6 комментариев
0

Вы можете пройти через хорошо написанный IRC-бот в Python Download

0

Я бы проверял логику в ваших условностях. Конструкция цикла должна работать.

  • 0
    Действительно странно, я прошел через все операторы if и похоже, что он должен работать.
0

Быть явным с тем, что в строке. Использование 0, 1, 2... n на самом деле является вашей ошибкой, и это делает код очень трудным для чтения в будущем для себя или для других. Поэтому позвольте использовать удобный кортеж, чтобы показать, что мы ожидаем от строки. Такие работы, как код, как документация

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

Это показывает читателю вашего кода то, что вы ожидаете от строки, которая будет содержать, и она показала бы вам вашу ошибку при первом запуске:)

  • 0
    for line in db уже итерации по каждой строке файла. Это функционально эквивалентно for line in db.readlines() но более эффективно использует память, поскольку не считывает весь файл в список.
  • 0
    Второе предложение хорошо, хотя.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню