2

I wrote a little program which downloads the latest daily tide graph from NOAA, adds a text table to the image containing tidal information, and then sets this image as my desktop wallpaper.

from bs4 import BeautifulSoup
import Image, ImageDraw, ImageFont
from urllib import urlretrieve
import urllib2
import time
import ctypes
import sys
import os
import datetime
import traceback


def Fetch_tideGraph():
    # Fetch the Tides Graph .gif
    #
    # Fetch the Station Home Page
    try:
        url = 'http://tidesandcurrents.noaa.gov/noaatidepredictions/viewDailyPredictions.jsp?Stationid=8637689'
        page = urllib2.urlopen(url)
        soup = BeautifulSoup(page.read())

        # Find the Url to the tides graph
        ImgElement = str(soup.find_all('input', { "alt" : "Daily Tide Prediction graphical plot" }))
        soup = BeautifulSoup(ImgElement)
        tag = soup.input
        src = str(tag['src'])
        imgUrl = 'http://tidesandcurrents.noaa.gov/noaatidepredictions' + src.lstrip('.')
        print imgUrl
    except Exception, e:
        print "Failed to Load Webpage"
        traceback.print_exc()
        raw_input('Press Enter to exit...')
        sys.exit()

    # Download the tide graph
    try:
        print "Downloading gif....."
        urlretrieve(imgUrl, "C:\\Users\\Jack\\Documents\\Py Projects\\tides.gif")
        # Allow time for image to save:
        time.sleep(5)
        print "Gif Downloaded."
    except:
        print "Failed to Download new GIF"
        raw_input('Press Enter to exit...')
        sys.exit()

    # Convert gif to jpg
    try:
        print "Converting GIF to JPG...."
        Image.open("C:\\Users\\Jack\\Documents\\Py Projects\\tides.gif").convert('RGB').save("C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg")
        print "Image Converted"
    except Exception, e:
        print "Conversion FAIL:", sys.exc_info()[0]
        traceback.print_exc()
        pass

def update_wallpaper():
    # Change the Wallpaper
    imgPath = 'C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg'
    SPI_SETDESKWALLPAPER = 20
    try:
        print "Updating WallPaper..."
        ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, imgPath, 0)
        print "Wallpaper Updated"
    except:
        print "Wallpaper update FAIL"
        raw_input('Press Enter to exit...')

def todays_tide():
    # Print Table of Todays Tides
    # Open Tide Tables and Image File:
    try:
        info = open('C:\\Users\\Jack\\Documents\\Py Projects\\AnnualTides.txt', 'r')
        img = Image.open('C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg')
    except IOError:
        print "Tide table look-up failed."
        traceback.print_exc()
    # Load Font:
    f = ImageFont.load_default()
    draw = ImageDraw.Draw(img)
    # Lookup todays tides by matching date to table:
    now = datetime.datetime.now()
    date = now.strftime("%Y/%m/%d")
    tomorrow = now.strftime("%Y/%m/") + str(now.day+1)
    # Draw on image:
    y = 30
    head = '   Date    Day Time      Ft cm High/Low'
    draw.text((150, 20), head, (0,0,0), font=f)
    for line in info.readlines():
        if date in line or tomorrow in line:
            line = line.replace('\t', ' ')
            draw.text((150, y), line, (0,0,0), font=f)
            y += 10
    info.close()
    img.save("C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg")




##########################################

def main():
    try:
        Fetch_tideGraph()
        todays_tide()
        update_wallpaper()
        raw_input('Press Enter to exit...')
    except:
        print "Error in main()", sys.exc_info()[0]
        raw_input('Press Enter to exit...')

###########################################

if __name__ == "__main__":
    main()

The code, despite being rather ugly, seems to work well enough save for one little bug that I can not seem to squash. Most of the time when I run the program everything goes smooth, but every couple of runs I get the following output:

>>> 
http://tidesandcurrents.noaa.gov/noaatidepredictions/serveimage?filename=images/8637689/21072012/855/8637689_2012-07-22.gif
Downloading gif.....
Gif Downloaded.
Converting GIF to JPG....
Conversion FAIL: <type 'exceptions.IOError'>
Traceback (most recent call last):
  File "C:\Users\Jack\Documents\Py Projects\Tides.py", line 54, in Fetch_tideGraph
    Image.open("C:\\Users\\Jack\\Documents\\Py Projects\\tides.gif").convert('RGB').save("C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg")
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 1980, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file
Updating WallPaper...
Wallpaper Updated
Press Enter to exit...
>>> 

Help me to understand and remedy this Error. Why does it only occur part of the time?

Jack
  • 242
  • 4
  • 18
  • 1
    We don't know. What does your input look like at those times? – Ignacio Vazquez-Abrams Jul 21 '12 at 15:12
  • @Ignacio Vazquez-Abrams Inputs are as follows: The tides.gif file is pulled from the NOAA website via the Fetch_tideGraph() function. I need this GIF in JPG format so I can work with it. The program fails when trying to convert the tides.gif to tides.jpg via: Image.open("C:\\Users\\Jack\\Documents\\Py Projects\\tides.gif").convert('RGB').save("C:\\Users\\Jack\\Documents\\Py Projects\\tides.jpg"). What other input information do I need to supply? – Jack Jul 21 '12 at 15:43
  • 1
    That's what the input is *expected* to be. What is the *actual* input. – Ignacio Vazquez-Abrams Jul 21 '12 at 15:47
  • 'tides'gif' exists but contains no, or limited, data. – Jack Jul 21 '12 at 16:16

1 Answers1

5

The IOError suggests your gif file is not complete, and thus not recognizable as an Image to PIL. The most likely issue is that your download is taking longer to complete than the 5 seconds you're allowing in the try: block to download the gif file.

You might try a couple other url-fetching approaches to make sure you get a complete file before continuing. This one has a progress bar, but also try here and here.

Community
  • 1
  • 1
khoxsey
  • 1,405
  • 9
  • 13
  • Sure enough, the download of my gif file is taking longer than 5 seconds resulting in an empty 'tides.gif' file. If I allow my program more time to fetch the gif via 'time.sleep(10)', it ups my success rate, however, the problem persists. How can I make my program execution wait for the completion of the gif download before continuing? – Jack Jul 21 '12 at 16:14
  • 2
    Three choices off the top of my head: 1) dig into the `urllib2` docs to find a blocking url fetch (so your script will wait until done); 2) catch the IOError explicitly and sleep() again, then loop; 3) shell out to another tool (curl or wget) to fetch the file, then continue. – khoxsey Jul 21 '12 at 19:40