tags:

views:

523

answers:

6

I'm learning Python as my second programming language (my first real one if you don't count HTML/CSS/Javascript). I'm trying to build something useful as my first real application - an IRC bot that alerts people via SMS when certain things happen in the channel. Per a request by someone, I'm (trying) to build in scheduling preferences where people can choose not to get alerts from between hours X and Y of the day.

Anyways, here's the code I'm having trouble with:

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

The only problem I'm having is somehow the script only ends up looping through one of the lines (or something like that) because I only get one result every time, even if I have more than one entry in the CSV file.

A: 

I would check the logic in your conditionals. You looping construct should work.

Harold
Really weird, I've stepped through the flow of the if statements and it seems like it should be working.
A: 

Be explicit with what's in a row. Using 0, 1, 2...n is actually your bug, and it makes code very hard to read in the future for yourself or others. So let's use the handy tuple to show what we're expecting from a row. This sort of works like code as documentation

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

This shows the reader of your code what you're expecting a line to contain, and it would have shown your bug to you the first time you ran it :)

Trey Stout
`for line in db` already iterates over each line of the file. It's functionally equivalent to `for line in db.readlines()` but more memory efficient, since it doesn't read the whole file into a list.
Miles
Second suggestion is good, though.
Miles
Ahh I didn't know the file iterated like that, thanks for the info. :)
Trey Stout
+5  A: 

Have you tried something more simple? Just to see how your file is actually read by Python:

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

There can be problem with format of your csv-file. That happens, for instance, when you open Unix file in Windows environment. In that case the whole file looks like single string as Windows and Unix have different line separators. So, I don't know certain cause of your problem, but offer to think in that direction.

Update: Your have multiple ways through the body of your loop:

  1. when s is "no": "They always want alerts, sending email" will be printed.
  2. when s is not "no" and curtime in nrt: "They don't want an alert during the current hour, not sending" will be printed.
  3. when s is not "no" and curtime in nrt is false (the last else): nothing will be printed and no other action undertaken.

Shouldn't you place some print statement in the last else branch?

Also, what is exact output of your snippet? Is it "They always want alerts, sending email"?

Rorick
This is a good way to go about debugging your problem.
James McMahon
Nope, it matches up.
Do both snippets stop with one result?
Rorick
No, this snippet lists all three results in the CSV but the other one only does one.
I've updated my answer
Rorick
What is exact output of your snippet? Is it "They always want alerts, sending email"?
Rorick
Filling it out with the code, it should be doing something like:when s is no: alert sentwhen s != no and curtime in nrt: no alertwhen s != no and curtime is not in nrt: alert sent
Sorry, I don't understand your comment. What results do you expect from your snippet? If they are messages in console, you won't see any unless s == "no" (having in mind Miles' answer also).
Rorick
+9  A: 

If this is a regular CSV file you should not try to parse it yourself. Use the standard library csv module.

Here is a short example from the docs:

import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
    print row
unbeknown
+1 for not re-inventing the wheel :)
bedwyr
+8  A: 

There are at least two bugs in your program:

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

First, curtime is a string, whereas nrt is a list of integers. Python is strongly typed, so the two are not interchangeable, and won't compare equal:

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

This revised code addresses that issue, and is also more efficient than generating a list and searching for the current hour in it:

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

A second issue that the above does not address is that your program will not behave properly if the hours wrap around midnight (e.g. s = 22 and f = 8).

Neither of these problems are necessarily related to "the script only ends up looping through one of the lines", but you haven't given us enough information to figure out why that might be. A more useful way to ask questions is to post a brief but complete code snippet that shows the behavior you are observing, along with sample input and the resulting error messages, if any (along with traceback).

Miles
A: 

You could go thro an existing well written IRC bot in Python Download

Lakshman Prasad