The comments in the code explain it profusely. In short, I've taken it as an oportunity to exercise not just the use of modules and parsing content from a website, but also the use of classes and inheritance. I've defined a parent class named data_retriever, which works as a dummy base, it just declare a container variable and defines a method that returns it. It doesn't have any real use in this case, but seems reasonable in another context, where this script could serve as a module for all kinds of data retrievement.
A child of data_retriever is from_url_retriever, which with it's proper elaboration shoud serve for retrieving from web sites in general, provided it's url. It's a more concret application of data_retriever, and that's the essence of hineritance.
Finally, it's defined a child of from_url_retriever, which is called yahoo_share_retriever. As from_url_retriever is a child of data_retriever, yahoo_share_retriever also inherits from data_retriever. This class, it's another concretion of useness, focused on a concret content of a concret web, This child, acts as a helper for printing the content of the preestablished website we plan to use regularly in our code (i.e. http://download.finance.yahoo.com)
1 #!/usr/bin/env python 2 3 # Assignment: Retrieve from http://download.finance.yahoo.com the share value 4 # of a given NASDAQ company's symbol. 5 # 6 #To achieve this, we need the urllib2 module. 7 # 8 9 import sys 10 import urllib2 11 12 13 class data_retriever (object): 14 15 """ 16 This class will serve as base class for retrieving content from urls. 17 Splitting this in two classes may be dumb, but it will serve as 18 an hineritance exercise as well. 19 20 """ 21 22 def __init__ (self): 23 self.content = None # Content is where all data will be stored 24 25 def return_data (): 26 27 """ 28 Will retrieve the data container, only if it's populated. 29 30 """ 31 32 if self.content: 33 return self.content 34 else: 35 print "Error. Data not retrieved properly" 36 37 38 class from_url_retriever (data_retriever): 39 """ 40 This class is a child of data_retriever. Inherits from it the variable 41 content, which serves as container for all the data, and the method 42 return_data, which serves for returning this data container. 43 44 This class adds the functionality to retrieve data from an url, using 45 urllib2 module, and defines the methods retrieve_from_url, which returns 46 an open file contining the content of the Url, and print_content, which 47 prints the whole content of the given Url. 48 49 """ 50 51 52 def __init__ (self, url): 53 data_retriever.__init__ (self) 54 self.url = url 55 56 57 def retrieve_from_url (self, url): 58 59 """ 60 This method uses the function urlopen from urllib2 module and 61 retrieves all content of the site to url_content, which is 62 a kind of file-object, already open 63 64 This method handles the URLError and ValueError exceptions, and exits 65 with an error message 66 67 """ 68 69 try: 70 url_content = urllib2.urlopen(url) 71 72 except urllib2.URLError: 73 error_message = "Your url <" + url + "> is wrong, please fix" 74 sys.exit(error_message) 75 76 except ValueError: 77 error_message = "Your url <" + url + "> has an unknown url" \ 78 " type. Please fix" 79 sys.exit(error_message) 80 81 else: 82 return url_content 83 84 85 def store_content (self): 86 87 """ 88 This method calls for retrieve_from_url method and stores its return 89 in content. 90 91 """ 92 93 self.open_file_content = self.retrieve_from_url (self.url) 94 self.content = self.open_file_content.read() 95 self.open_file_content.close() # The return of urllib2.urlopen() is a 96 # kind of file, closing it for safety 97 98 99 def print_content (self): 100 101 """ 102 Calls for store_content() and prints content if not empty. 103 104 """ 105 106 self.store_content() 107 if self.content: 108 print self.content 109 else: 110 error_message = "Something went wrong. Fix it" 111 sys.exit(error_message) 112 113 114 class yahoo_share_retriever (from_url_retriever): 115 116 """ 117 This class is a child of from_url_retriever, which sets the link 118 for yahoo share value download service, and asks for it's argument 119 only the company's symbol. Instead of asking for the url as 120 from_url_retriever, it uses the download.finance.com service of Yahoo. 121 122 In order to choose which company you want to search, we hardcode the 123 link splitted in 2 halves, and we keep it in a list. once an instance 124 is created, the constructor asks for nasdaq_symbol, which we insert in the 125 middle of the 2 halves (position 1 in url list) and then we join the list 126 into one single string,which we then pass to from_url_retriever constructor. 127 128 Using this class, everything is prepared for be able to print just by 129 creating an instance and calling print_content(). print_content overrides 130 print_content from the parent class, to strip the content which is provided 131 with '\r\n', and print an aproppiate message 132 133 """ 134 135 def __init__ (self, nasdaq_symbol): 136 137 if nasdaq_symbol.isalpha(): # Risky, dont' know if they are only 138 # only alphabets, but anyway... 139 140 url = ["http://download.finance.yahoo.com" 141 "/d/quotes.csv?s=", "&f=l1"] 142 url.insert(1, nasdaq_symbol) 143 url = "".join(url) 144 145 else: 146 error_message = nasdaq_symbol + " is not a correct NASDAQ symbol" 147 sys.exit(error_message) 148 149 from_url_retriever.__init__ (self, url) 150 self.nasdaq_symbol = nasdaq_symbol.upper() # We keep it for output 151 152 153 def print_content(self): 154 155 """ 156 Overriden method that strips content to adapt the concret content of 157 the Yahoo service, and prints an aproppiate message. 158 159 Yahoo service will generate a cvs file even if the symbol is incorrect. 160 It will contain 0.00, which is not good. This code makes sure it's 161 a desired output, or tells the user it's a wrong symbol 162 163 """ 164 165 self.store_content() 166 self.content = self.content.rstrip("\r\n") 167 168 if self.content.find("0.00") >= 0: 169 error_message = "The NASDAQ symbol '" + self.nasdaq_symbol +"' is" \ 170 " incorrect. Please make sure you provide a" \ 171 " correct symbol." 172 sys.exit(error_message) 173 174 else: 175 print "Share value for %s: %s" % (self.nasdaq_symbol, self.content) 176 177 178 if __name__ == "__main__": 179 180 if len(sys.argv) == 2: 181 yahoo_share_retriever (sys.argv[1]).print_content() 182 sys.exit(0) 183 184 else: 185 sys.exit("Usage: ./sharevalue.py <NASDAQ_SYMBOL>")