0

I am trying to write a list of data to an excel spreadsheet. Something is going wrong when I try to iterate over my entire list in parallel. I get the following error:

File "canadascript.py", line 57, in <module>
    sheet.write(row, high0_col, c.high0)
AttributeError: 'tuple' object has no attribute 'high0'

I am importing a separate script that successfully returns all the variables (high0, low0, etc.). This is the script I am running when I receive the error:

#!/usr/bin/env python

from xlutils.copy import copy
from xlrd import open_workbook

import canada

#import os

#os.chdir("/data/ops/Ops Documents/MexTemps")


cities = canada.getCities()

for c in cities :
        c.retrieveTemps()

## 
# writing to excel
##
file_name = 'fcst_hilo_TEST.xls'
new_file_name = 'fcst_hilo.xls'
row = 1

# column constants
high0_col = 1
low1_col = 2
high1_col = 3
low2_col = 4
high2_col = 5
low3_col = 6
high3_col = 7
low4_col = 8
high4_col = 9
low5_col = 10
high5_col = 11
low6_col = 12
high6_col = 13
low7_col = 14
high7_col = 15

workbook_file = None
try :
        # currently xlwt does not implement this option for xslx files
        workbook_file = open_workbook(file_name, formatting_info=True)
except :
        workbook_file = open_workbook(file_name)

workbook = copy(workbook_file)
sheet = workbook.get_sheet(0)

# iterate over list in parallel, zip returns a tuple 
for c in zip(cities) :
        sheet.write(row, high0_col, c.high0)
        sheet.write(row, low1_col, c.low1)
        sheet.write(row, high1_col, c.high1)
        sheet.write(row, low2_col, c.low2)
        sheet.write(row, high2_col, c.high2)
        sheet.write(row, low3_col, c.low3)
        sheet.write(row, high3_col, c.high3)
        sheet.write(row, low4_col, c.low4)
        sheet.write(row, high4_col, c.high4)
        sheet.write(row, low5_col, c.low5)
        sheet.write(row, high5_col, c.high5)
        sheet.write(row, low6_col, c.low6)
        sheet.write(row, high6_col, c.high6)
        sheet.write(row, low7_col, c.low7)
        sheet.write(row, high7_col, c.high7)

workbook.save(new_file_name)

EDIT:

Here is the script I import into this one:

#!usr/bin/env python

import urllib
from datetime import datetime
from datetime import timedelta

date = datetime.now()
date1 = date + timedelta(days=1)
date2 = date + timedelta(days=2)
date3 = date + timedelta(days=3)
date4 = date + timedelta(days=4)
date5 = date + timedelta(days=5)
date6 = date + timedelta(days=6)

class city :
        def __init__(self, city_name, link) :
                self.name = city_name
                self.url = link
                self.high0 = 0
                self.high1 = 0
                self.high2 = 0
                self.high3 = 0
                self.high4 = 0
                self.high5 = 0
                self.high6 = 0
                self.high7 = 0
                self.low1 = 0
                self.low2 = 0
                self.low3 = 0
                self.low4 = 0
                self.low5 = 0
                self.low6 = 0
                self.low7 = 0

        def retrieveTemps(self) :
                filehandle = urllib.urlopen(self.url)

                # get lines from result into array
                lines = filehandle.readlines()

                # (for each) loop through each line in lines
                line_number = 0 # a counter for line number
                for line in lines:
                        line_number = line_number + 1 # increment counter

                        # find string, position otherwise position is -1

                        position0 = line.rfind('title="{}"'.format(date.strftime("%A")))
                        position1 = line.rfind('title="{}"'.format(date1.strftime("%A")))
                        position2 = line.rfind('title="{}"'.format(date2.strftime("%A")))
                        position3 = line.rfind('title="{}"'.format(date3.strftime("%A")))
                        position4 = line.rfind('title="{}"'.format(date4.strftime("%A")))
                        position5 = line.rfind('title="{}"'.format(date5.strftime("%A")))
                        position6 = line.rfind('title="{}"'.format(date6.strftime("%A")))
                        if position0 > 0 :
                                self.high0 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low1 = lines[line_number + 18].split('&')[0].split('>')[-1]

                        if position1 > 0 :
                                self.high1 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low2 = lines[line_number + 19].split('&')[0].split('>')[-1]

                        if position2 > 0 :
                                self.high2 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low3 = lines[line_number + 19].split('&')[0].split('>')[-1]

                        if position3 > 0 :
                                self.high3 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low4 = lines[line_number + 19].split('&')[0].split('>')[-1]

                        if position4 > 0 :
                                self.high4 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low5 = lines[line_number + 19].split('&')[0].split('>')[-1]

                        if position5 > 0 :
                                self.high5 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.low6 = lines[line_number + 19].split('&')[0].split('>')[-1]
                                self.low7 = lines[line_number + 19].split('&')[0].split('>')[-1]

                        if position6 > 0 :
                                self.high6 = lines[line_number + 4].split('&')[0].split('>')[-1]
                                self.high7 = lines[line_number + 4].split('&')[0].split('>')[-1]

                                break # done with loop, break out of it

                filehandle.close()

#BRITISH COLUMBIA CITIES

def getCities():

        c1 = city('Prince George', 'http://www.weatheroffice.gc.ca/city/pages/bc-79_metric_e.html')
        c2 = city('Kamloops', 'http://www.weatheroffice.gc.ca/city/pages/bc-45_metric_e.html')
        c3 = city('Blue River', 'http://www.weatheroffice.gc.ca/city/pages/bc-22_metric_e.html')
        c4 = city('High Level', 'http://www.weatheroffice.gc.ca/city/pages/ab-24_metric_e.html')
        c5 = city('Peace River', 'http://www.weatheroffice.gc.ca/city/pages/ab-25_metric_e.html')
        c6 = city('Jasper', 'http://www.weatheroffice.gc.ca/city/pages/ab-70_metric_e.html')
        c7 = city('Edmonton', 'http://www.weatheroffice.gc.ca/city/pages/ab-50_metric_e.html')
        c8 = city('Calgary', 'http://www.weatheroffice.gc.ca/city/pages/ab-52_metric_e.html')

#SASKATCHEWAN CITIES

        c9 = city('Biggar', 'http://www.weatheroffice.gc.ca/city/pages/sk-2_metric_e.html')
        c10 = city('Saskatoon', 'http://www.weatheroffice.gc.ca/city/pages/sk-40_metric_e.html')
        c11 = city('Melville', 'http://www.weatheroffice.gc.ca/city/pages/sk-8_metric_e.html')
        c12 = city('Canora', 'http://www.weatheroffice.gc.ca/city/pages/sk-3_metric_e.html')
        c13 = city('Yorkton', 'http://www.weatheroffice.gc.ca/city/pages/sk-33_metric_e.html')

#MANITOBA CITIES

        c14 = city('Winnipeg', 'http://www.weatheroffice.gc.ca/city/pages/mb-38_metric_e.html')
        c15 = city('Sprague', 'http://www.weatheroffice.gc.ca/city/pages/mb-23_metric_e.html')

#ONTARIO CITIES

        c16 = city('Thunder Bay', 'http://www.weatheroffice.gc.ca/city/pages/on-100_metric_e.html')
        c17 = city('Sioux Lookout', 'http://www.weatheroffice.gc.ca/city/pages/on-135_metric_e.html')
        c18 = city('Armstrong', 'http://www.weatheroffice.gc.ca/city/pages/on-111_metric_e.html')
        c19 = city('Hornepayne', 'http://www.weatheroffice.gc.ca/city/pages/on-78_metric_e.html')
        c20 = city('Sudbury', 'http://www.weatheroffice.gc.ca/city/pages/on-40_metric_e.html')
        c21 = city('South Parry', 'http://www.weatheroffice.gc.ca/city/pages/on-103_metric_e.html')
        c22 = city('Toronto', 'http://www.weatheroffice.gc.ca/city/pages/on-143_metric_e.html')
        c23 = city('Kingston', 'http://www.weatheroffice.gc.ca/city/pages/on-69_metric_e.html')
        c24 = city('Cornwall', 'http://www.weatheroffice.gc.ca/city/pages/on-152_metric_e.html')

#QUEBEC CITIES

        c25 = city('Montreal', 'http://www.weatheroffice.gc.ca/city/pages/qc-147_metric_e.html')
        c26 = city('Quebec', 'http://www.weatheroffice.gc.ca/city/pages/qc-133_metric_e.html')
        c27 = city('La Tuque', 'http://www.weatheroffice.gc.ca/city/pages/qc-154_metric_e.html')
        c28 = city('Saguenay', 'http://www.weatheroffice.gc.ca/city/pages/qc-166_metric_e.html')
        c29 = city('Riviere-du-loup', 'http://www.weatheroffice.gc.ca/city/pages/qc-108_metric_e.html')

#NOVA SCOTIA CITIES

        c30 = city('Truro', 'http://www.weatheroffice.gc.ca/city/pages/ns-25_metric_e.html')
        c31 = city('Halifax', 'http://www.weatheroffice.gc.ca/city/pages/ns-19_metric_e.html')

#NEW BRUNSWICK CITIES

        c32 = city('Edmundston', 'http://www.weatheroffice.gc.ca/city/pages/nb-32_metric_e.html')
        c33 = city('Moncton', 'http://www.weatheroffice.gc.ca/city/pages/nb-36_metric_e.html')
        c34 = city('Sarnia', 'http://www.weatheroffice.gc.ca/city/pages/on-147_metric_e.html')

        cities = []
        cities.append(c1)
        cities.append(c2)
        cities.append(c3)
        cities.append(c4)
        cities.append(c5)
        cities.append(c6)
        cities.append(c7)
        cities.append(c8)
        cities.append(c9)
        cities.append(c10)
        cities.append(c11)
        cities.append(c12)
        cities.append(c13)
        cities.append(c14)
        cities.append(c15)
        cities.append(c16)
        cities.append(c17)
        cities.append(c18)
        cities.append(c19)
        cities.append(c20)
        cities.append(c21)
        cities.append(c22)
        cities.append(c23)
        cities.append(c24)
        cities.append(c25)
        cities.append(c26)
        cities.append(c27)
        cities.append(c28)
        cities.append(c29)
        cities.append(c30)
        cities.append(c31)
        cities.append(c32)
        cities.append(c33)
        cities.append(c34)

return (cities)

Any ideas? Thanks!

5
  • Can you show how you retrieve the tuples from canada.getCities() ? Commented Sep 18, 2013 at 17:57
  • 3
    Where you are doing the same thing again and again, you should be using a loop and a data structure - there are some huge anti-patterns in your code. Commented Sep 18, 2013 at 17:58
  • @MatteoD - I have edited to the above code to show that. Lattyware - I figured there would be a simpler way to do all that, but I am new at this and don't know all the best ways just yet. Commented Sep 18, 2013 at 18:03
  • 2
    What line does the error occur at? Could you please post the exact error notification output from the interpreter? Commented Sep 18, 2013 at 18:04
  • @Asad - I have included that in the edit. Commented Sep 18, 2013 at 18:07

2 Answers 2

3

The error is on the expression c.high0.

If you look at what c is, it's one of the elements of a zip:

for c in zip(cities) :

And that means it's a tuple. That's what zip does: it takes an iterable of sequences, and turns it into an iterable of tuples, where each tuple has one member of each sequence.

If you can explain what you expected each c to be, or why you're calling zip, we could probably explain how to do it properly.

Sign up to request clarification or add additional context in comments.

4 Comments

I am calling zip because if I just use for c in cities, it will only return the last item in the loop (from canada.py). This way does successfully input everything I need in the excel file, but it only does it for the last city on the list (not all 34 cities). To show you what I mean I will inlcude all of the canada.py script that I import in the original post.
@hunter21188: I still don't understand what you were expecting that zip to do. All that would mean is that instead of getting all components of only the last value, you get only the last component of each value. (If that's really what you want, zip(*cities) is the answer… but I doubt it's what you want.)
@hunter21188: Also, when you're confused by things like this, try printing out the intermediate values, or stepping through in a debugger. If you print zip(cities) (Python 2.x) or print(list(zip(cities))) (Python 3.x), you should understand what's happening.
Alright, thank you for your help. My problem regarding the tuple error was solved, but it turns out that was not the underlying problem. Therefore, I will create a new question regarding that problem. Thanks again.
2

I also don't understand why you need to use zip(), but if you are positive you need it, try it like this:

for c in zip(cities):
    sheet.write(row, high0_col, c[0].high0)
    sheet.write(row, low1_col, c[0].low1)
    sheet.write(row, high1_col, c[0].high1)
    sheet.write(row, low2_col, c[0].low2)
    sheet.write(row, high2_col, c[0].high2)
    sheet.write(row, low3_col, c[0].low3)
    sheet.write(row, high3_col, c[0].high3)
    sheet.write(row, low4_col, c[0].low4)
    sheet.write(row, high4_col, c[0].high4)
    sheet.write(row, low5_col, c[0].low5)
    sheet.write(row, high5_col, c[0].high5)
    sheet.write(row, low6_col, c[0].low6)
    sheet.write(row, high6_col, c[0].high6)
    sheet.write(row, low7_col, c[0].low7)
    sheet.write(row, high7_col, c[0].high7)

This way you are acessing the first (and only) element of the tuple created by zip(cities).

Again, I dont see why you can't use for c in cities:, which looks way better, but this might solve your problem.

2 Comments

Alright, that did give me the exact same output as for c in cities, so apparently I am missing something. I have 34 columns in excel that I need to input that data into. column 1 is city1, column 2 is city 2, etc... When I use for c in cities, it fills in only the first column with city34. Everything else is blank.
Wait a minute, now I see what might be wrong: You're overwriting everything. You only get the last item not because you're iterating the list wrong, but because you are writing the same row and columns for every city. Try adding row = row + 1 at the end of your for loop

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.