Advice Criticism on Python App

Discussion in 'Python' started by Jimbo, Mar 24, 2010.

  1. Jimbo

    Jimbo Guest

    I have made a Python App(really script) that will check a stocks
    current values from a website & save that data to a SQLite 3 database.

    I am looking for any suggestions & criticisms on what I should do
    better or anything at all but mainly in these areas:
    Any advice criticism would be really helpful.

    App:
    Code:
    """
     *Stock Data Builder*
       Algorithm:
          - Search website for stock
          - Get website HTML source code
          - Search code for target stock data(price,dividends,etc..)
          - Add data to text file
    """
    
    import sys
    import os
    import sqlite3
    import datetime
    import time
    import urllib2
    
    ### Global Variables ###
    menu = "***Stock Program*** \n\n1. Add a Stock to track \n2. Get
    Todays Tracking Data \n3. Exit \nEnter decision: "
    target = '<th scope="row" class="row"><a href="/asx/research/
    companyInfo.do?by=asxCode&asxCode=%s">%s</a>'
    ASXurl = 'http://www.asx.com.au/asx/markets/priceLookup.do?
    by=asxCodes&asxCodes='
    
    class stock:
        code             = ""
        purchasePrice    = 0
        purchaseQuantity = 0
        price            = []  # list of recent prices
        recentBid        = []  # list of recent bids for stock
        recentOffer      = []  # list of recent offers for stock
        stockVol         = []  # list of stock quantity available on
    market
        def __init__(self):
            """ Default Constructor """
            self.code             = ""
            self.purchasePrice    = 0
            self.purchaseQuantity = 0
    
        def constructor(self, stockCode, purPrice, purQuant):
            """ Constructor """
            self.code             = stockCode
            self.purchasePrice    = purPrice
            self.purchaseQuantity = purQuant
    
        def setData(self, stockCode, purPrice, purQuant, priceList,
    reBidList, reOffList, popList):
            """ Defines & implements the objects' public variables """
            self.code             = stockCode
            self.purchasePrice    = purPrice
            self.purchaseQuantity = purQuant
            self.price            = priceList
            self.recentBid        = reBidList
            self.recentOffer      = reOffList
            self.stockVol         = popList
    
            self.printStats()
    
        def updateData(self, priceEle, bidEle, offerEle, populEle):
            """ Adds data to stock object's lists """
            self.price.append(priceEle)
            self.recentBid.append(bidEle)
            self.recentOffer.append(offerEle)
            self.stockVol.append(populEle)
    
        def printStats(self):
            """ Output Stock attributes """
    
            print("Stock Code: "+self.code)
            print("Stock Purchase Price: "+str(self.purchasePrice))
            print("Stock Quantity Owned: "+str(self.purchaseQuantity))
            print("***Initial Investment Value:
    "+str(self.purchasePrice*self.purchaseQuantity))
            if not(len(self.price) <= 0):
                print("Stock Current Price: "+str(self.price[-1]))
                print("Recent Bid: "+str(self.recentBid[-1]))
                print("Recent Offer: "+str(self.recentOffer[-1]))
                print("Total Stock Volume in market:
    "+str(self.stockVol[-1]))
                print("***Present Investment Value:
    "+str(self.price[-1]*self.purchaseQuantity))
            print("\n")
    
    
    ### Functions ###
    def connectDatabase(dbLocation, dbName, tableName):
        """ Establish & Return connection to SQLite Database """
    
        try:
            if not (os.path.exists(dbLocation)):
                os.mkdir(dbLocation) # create folder/dir
    
            os.chdir(dbLocation)        # change directory focus to
    dbLocation
            conn = sqlite3.connect(dbLocation+dbName)
            cur = conn.cursor()
            try:
                createTableQ = "CREATE TABLE IF NOT EXISTS "+tableName
    +" (code varchar PRIMARY KEY, purchase_price float, purchase_quantity
    float, purchase_date varchar);"
                cur.execute(createTableQ)
                conn.commit()
            except:
                pass
            return conn
        except IOError or OSError:
            print "Connection to database failed"
            return False
    
    def retrieveStockDatabase(conn, tableName):
        """ Read SQLite3 database & extract stock data into StockList """
    
        stockList  = []
        stockQuery = "select recent_price, recent_offer, recent_bid,
    stock_volume from ? ;"
        cur = conn.cursor()
        cur.execute("select code, purchase_price, purchase_quantity from
    "+tableName+";")
    
        for row in cur.fetchall():
            newStock = stock()
            newStock.code             = row[0]
            newStock.purchasePrice    = row[1]
            newStock.purchaseQuantity = row[2]
            cur.execute(stockQuery,[newStock.code])
            for rw in cur.fetchall():
                newStock.price.append(rw[0])
                newStock.recentOffer.append(rw[1])
                newStock.recentBid.append(rw[2])
                newStock.stockVol.append(rw[3])
            stockList.append(newStock)
    
        return stockList
    
    def getDate():
        """ Return todays date in format DD:MM:YYYY """
        time = datetime.datetime.now()
        date = time.strftime("%d:%m:%Y") # string format time (%y)
        return date
    
    def newStockDatabase(conn, stockTable, stock):
        """ Add a new stock to SQLite database if not already there
            We save the stocks code, purchase price, quantity purchased
            & date of purchase.                                       """
        cur = conn.cursor()
        try:
            createTableQ = "create table "+stock.code+" (date varchar
    PRIMARY KEY, recent_price float, recent_offer float, recent_bid float,
    stock_volume double);"
            stockQuery   = "insert into "+stockTable+"
    values(?, ?, ?, ?);"
            cur.execute(createTableQ)
            cur.execute(stockQuery,
    [stock.code,stock.purchasePrice,stock.purchaseQuant,getDate()])
            conn.commit()
        except IOError or OSError:
            print "Table may already exist or bad SQLite connection."
            return False
    
    def webFormat(URL):
    
        if (URL.startswith("http://")==False):
            URL = "http://"+URL
    
        return URL
    
    def getSource(URL):
        """ Retrieve HTML source code from website URL &
            save in sourceBuffer                       """
    
        try:
            URL = webFormat(URL) # make sure URL contains essential
    "http://"
            sourceBuffer = urllib2.urlopen(URL)
            print '\nResponse code = ',sourceBuffer.code
            print 'Response headers = ',sourceBuffer.info()
            print 'Actual URL = ',sourceBuffer.geturl()
            sourceCode = sourceBuffer.read()
            sourceBuffer.close()
            return sourceCode
    
        except IOError:  # URLError
            print "Function Failed: Reasons could be invalid URL name \nOR
    \nHTML protocol message transfer failure."
            return False # function failed
    
    def getTargetText(targetStrtData, targetEndData, dataBuffer):
        """ Grabs target text that lies inside 'dataBuffer' string
            between targetStrtData & targetEndData                """
    
        try:
            result = dataBuffer.split(targetStrtData)
            result.pop(0)
            result = result[0].split(targetEndData)
            result.pop(1)
            print result
            return result
        except IOError:
            print "Function Failed: Reasons could be targetStrtData and/or
    targetEndData is not present in dataBuffer."
    
    def getStockData(htmlText, selectedStock):
        """ Extract stock data(stock code,price,etc) from htmlText """
        try:
            # Here I extract my number data from HTML text
            tempList = []
            for string in htmlText:
                for i in string.split('>'):
                    for e in i.split():
                            if ('.' in e and e[0].isdigit()):
                                tempList.append(float(e))
                            elif (',' in e and e[0].isdigit() ):
                                # remove ',' chars
                                e = e.replace(',','')
                                tempList.append(float(e))
    
     
    selectedStock.updateData(tempList[0],tempList[2],tempList[3],tempList[7])
    
        except IOError:  # is this the correct error I should be trying to
    catch here??
            print "Function Failed: Reasons could be: sites HTML data has
    changed. Consult author of program."
            return False
    
    def createStockTracker(stockCode,stockPrice,stockQuant, stockList):
        """ Add a new stock to the database to track """
        newStock = stock()
        newStock.constructor(stockCode,stockPrice,stockQuant)
        stockList.append(newStock)
        return stockList
    
    def writeStockToDatabase(conn, stock):
        """ Write ONLY this Stock's attributes to SQLite Database """
    
        cur = conn.cursor()
        date = getDate()
    
        tableName = stock.code
        stockquery = "insert into "+tableName+" values(?, ?, ?, ?, ?);"
        cur.execute(query,[date,stock.price[-1], stock.recentOffer[-1],
    stock.recentBid[-1], stock.stockVol[-1]])
        conn.commit()
    
    def writeAllToDatabase(conn, stockList):
        """ Enter recent Stock attributes into SQLite Database """
    
        cur = conn.cursor()
        date = getDate()
    
        for stock in stockList:
            tableName = stock.code
            stockquery = "insert into "+tableName+"
    values(?, ?, ?, ?, ?);"
            cur.execute(query,[date,stock.price[-1],
    stock.recentOffer[-1], stock.recentBid[-1], stock.stockVol[-1]])
            conn.commit()
    
    ### Input Functions ###
    def inputNewStock():
        """ """
        print "*Please note only an Australian Securities Exchange(ASX)
    listed stock can be tracked in Version 1.0."
        badInput = True
    
        while (badInput == True):
            try:
                code     = raw_input("Please enter the ASX code for the
    stock you wish to track: ")
                price    = input("Please enter the individual stock value
    for "+code+": ")
                quantity = input("Please enter the number/quantity of
    stocks purchased: ")
                if (len(code)>3):
                    badInput = True
                else : badInput = False
                return True
            except IOError:
                if (raw_input("Incorrect input. Note: ASX code cannot be
    more than 3 chars. Press 'x' to exit or anything else to try
    again")=='x'):
                    return False
            badInput = True # this I am not sure if necessary to loop
    correctly
    
    
    ### Main program loop ###
    def main():
        programEnd = False;
        dbLocation = "C:\Users\Sam\Desktop\StockApp/"
        dbName     = "stockData.db"
        stockTable = "stocks"
    
        conn = connectDatabase(dbLocation,dbName,stockTable)
        stockList = retrieveStockDatabase(conn,stockTable)
    
        for s in stockList:
            s.printStats()
    
        while (programEnd == False):
    
            decision = input(menu) # Print Menu
    
            if (decision==1):
    
                if not(inputNewStock()==False):
                    stockList =
    createStockTracker(acode,price,quantity,stockList)
                    newStockDatabase(conn,stockTable,stockList[-1])
                    print("\n** New Stock **")
                    stockList[-1].printStats()
                    print "The stock "+code+" was successfully added to
    our database. \nNow every time the program runs it will automatically
    track this stock & obtain its stock attributes\n\n"
                    # TO DO:
                    # get new stock recent Data from internet etc.
                    # add stock data to data base;
            elif (decision==2):
                if (len(stockList)>0):
                    for Stock in stockList:
                        URL = ASXurl+Stock.code
                        sourceCode = getSource(URL)
                        targetData = getTargetText(target %
    (Stock.code,Stock.code),"</tr>",sourceCode)
                        getStockData(targetData,Stock)
                        Stock.printStats()
                        #writeStockToDatabase(conn,Stock)
                else:
                    print "You must first identify a stock to follow.
    \nPlease select option 1."
            elif (decision==3):
                print "Thank you for using Stock Program. Goodbye.\n"
                programEnd = True; # Exit program
    
        conn.close()
        return 0 # End program
    
    main()
     
    Jimbo, Mar 24, 2010
    #1
    1. Advertising

  2. Jimbo

    Chris Rebert Guest

    On Tue, Mar 23, 2010 at 5:05 PM, Jimbo <> wrote:
    > I have made a Python App(really script) that will check a stocks
    > current values from a website & save that data to a SQLite 3 database.
    >
    > I am looking for any suggestions & criticisms on what I should do
    > better or anything at all but mainly in these areas:

    <snip>
    > Any advice criticism would be really helpful.


    Complying with Python naming conventions would be one place to start:
    * Class names should be in StudlyCaps (so class "Stock", not class "stock").
    * Constants should be in UPPERCASE_WITH_UNDERSCORES.
    * Most other names should be words_separated_by_underscores, not
    camelCaseLikeThis; FWIW, I'm not a fan of this part of the guideline
    personally.

    Also, conditions don't need parentheses around them. So:
    if (decision == 1): #WRONG! harder to read, extra syntactic noise
    if decision == 1: #RIGHT

    For many more style details, see PEP 8 -- Style Guide for Python Code:
    http://www.python.org/dev/peps/pep-0008/

    Additionally, the "return 0" in main() serves no purpose; the return
    value isn't used as the exit code for the program. You can either
    eliminate the line entirely or use plain "return" if you want the
    extra clarity.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Mar 24, 2010
    #2
    1. Advertising

  3. Jimbo

    MRAB Guest

    Jimbo wrote:
    > I have made a Python App(really script) that will check a stocks
    > current values from a website & save that data to a SQLite 3 database.
    >
    > I am looking for any suggestions & criticisms on what I should do
    > better or anything at all but mainly in these areas:
    >
    >
    > Any advice criticism would be really helpful.
    >
    > App:
    >
    Code:
    """
    >  *Stock Data Builder*
    >    Algorithm:
    >       - Search website for stock
    >       - Get website HTML source code
    >       - Search code for target stock data(price,dividends,etc..)
    >       - Add data to text file
    > """
    > 
    > import sys
    > import os
    > import sqlite3
    > import datetime
    > import time
    > import urllib2
    > 
    > ### Global Variables ###
    > menu = "***Stock Program*** \n\n1. Add a Stock to track \n2. Get
    > Todays Tracking Data \n3. Exit \nEnter decision: "
    > target = '<th scope="row" class="row"><a href="/asx/research/
    > companyInfo.do?by=asxCode&asxCode=%s">%s</a>'
    > ASXurl = 'http://www.asx.com.au/asx/markets/priceLookup.do?
    > by=asxCodes&asxCodes='
    > 
    > class stock:
    >     code             = ""
    >     purchasePrice    = 0
    >     purchaseQuantity = 0
    >     price            = []  # list of recent prices
    >     recentBid        = []  # list of recent bids for stock
    >     recentOffer      = []  # list of recent offers for stock
    >     stockVol         = []  # list of stock quantity available on
    > market[/color]
    
    This will be variables belonging to the class itself, not instances of
    it.
    [color=blue]
    >     def __init__(self):
    >         """ Default Constructor """
    >         self.code             = ""
    >         self.purchasePrice    = 0
    >         self.purchaseQuantity = 0
    > 
    >     def constructor(self, stockCode, purPrice, purQuant):
    >         """ Constructor """
    >         self.code             = stockCode
    >         self.purchasePrice    = purPrice
    >         self.purchaseQuantity = purQuant
    > 
    >     def setData(self, stockCode, purPrice, purQuant, priceList,
    > reBidList, reOffList, popList):
    >         """ Defines & implements the objects' public variables """
    >         self.code             = stockCode
    >         self.purchasePrice    = purPrice
    >         self.purchaseQuantity = purQuant
    >         self.price            = priceList
    >         self.recentBid        = reBidList
    >         self.recentOffer      = reOffList
    >         self.stockVol         = popList
    > 
    >         self.printStats()
    > 
    >     def updateData(self, priceEle, bidEle, offerEle, populEle):
    >         """ Adds data to stock object's lists """
    >         self.price.append(priceEle)
    >         self.recentBid.append(bidEle)
    >         self.recentOffer.append(offerEle)
    >         self.stockVol.append(populEle)
    > 
    >     def printStats(self):
    >         """ Output Stock attributes """
    > 
    >         print("Stock Code: "+self.code)[/color]
    
    In Python 2 'print' is a statement, so it doesn't need its arguments to
    be enclosed in (). You could also use Python's string formatting:
    
             print "Stock Code: %s" % self.code
    [color=blue]
    >         print("Stock Purchase Price: "+str(self.purchasePrice))
    >         print("Stock Quantity Owned: "+str(self.purchaseQuantity))
    >         print("***Initial Investment Value:
    > "+str(self.purchasePrice*self.purchaseQuantity))
    >         if not(len(self.price) <= 0):[/color]
    
    'not' has a lower priority than '<=', and this can be simplified anyway:
    
             if len(self.price) > 0:
    
    or even:
    
             if self.price:
    
    because empty containers (eg lists) are treated as False, non-empty ones
    as True, by 'if' and 'while' statements.
    [color=blue]
    >             print("Stock Current Price: "+str(self.price[-1]))
    >             print("Recent Bid: "+str(self.recentBid[-1]))
    >             print("Recent Offer: "+str(self.recentOffer[-1]))
    >             print("Total Stock Volume in market:
    > "+str(self.stockVol[-1]))
    >             print("***Present Investment Value:
    > "+str(self.price[-1]*self.purchaseQuantity))
    >         print("\n")
    > 
    > 
    > ### Functions ###
    > def connectDatabase(dbLocation, dbName, tableName):
    >     """ Establish & Return connection to SQLite Database """
    > 
    >     try:
    >         if not (os.path.exists(dbLocation)):
    >             os.mkdir(dbLocation) # create folder/dir
    > 
    >         os.chdir(dbLocation)        # change directory focus to
    > dbLocation[/color]
    
    It's normally easier to use absolute paths instead of changing the
    current directory.
    [color=blue]
    >         conn = sqlite3.connect(dbLocation+dbName)[/color]
    
    It's better to join paths using os.path.join() because that will insert
    any directory separators for you.
    [color=blue]
    >         cur = conn.cursor()
    >         try:
    >             createTableQ = "CREATE TABLE IF NOT EXISTS "+tableName
    > +" (code varchar PRIMARY KEY, purchase_price float, purchase_quantity
    > float, purchase_date varchar);"
    >             cur.execute(createTableQ)
    >             conn.commit()
    >         except:
    >             pass[/color]
    
    DON'T USE BARE EXCEPTS, especially if you're just going to ignore the
    exception. Exceptions can be raised for a variety of reasons, including
    one you didn't expect due to bugs, so catch only what you expect.
    [color=blue]
    >         return conn
    >     except IOError or OSError:[/color]
    
    The result of:
    
         IOError or OSError
    
    is:
    
         IOError
    
    What you want is:
    
         except (IOError, OSError):
    
    Note: the parentheses are necessary here, otherwise it it would mean
    "catch an IOError exception and then bind it to the name 'OSError'".
    [color=blue]
    >         print "Connection to database failed"
    >         return False
    > [/color]
    Some times you return the connection, and other times False. A more
    usual value than False in such cases is None (unless you're returning
    True or False).
    [color=blue]
    > def retrieveStockDatabase(conn, tableName):
    >     """ Read SQLite3 database & extract stock data into StockList """
    > 
    >     stockList  = []
    >     stockQuery = "select recent_price, recent_offer, recent_bid,
    > stock_volume from ? ;"
    >     cur = conn.cursor()
    >     cur.execute("select code, purchase_price, purchase_quantity from
    > "+tableName+";")
    > 
    >     for row in cur.fetchall():
    >         newStock = stock()
    >         newStock.code             = row[0]
    >         newStock.purchasePrice    = row[1]
    >         newStock.purchaseQuantity = row[2]
    >         cur.execute(stockQuery,[newStock.code])
    >         for rw in cur.fetchall():
    >             newStock.price.append(rw[0])
    >             newStock.recentOffer.append(rw[1])
    >             newStock.recentBid.append(rw[2])
    >             newStock.stockVol.append(rw[3])
    >         stockList.append(newStock)
    > 
    >     return stockList
    > 
    > def getDate():
    >     """ Return todays date in format DD:MM:YYYY """
    >     time = datetime.datetime.now()
    >     date = time.strftime("%d:%m:%Y") # string format time (%y)
    >     return date
    > 
    > def newStockDatabase(conn, stockTable, stock):
    >     """ Add a new stock to SQLite database if not already there
    >         We save the stocks code, purchase price, quantity purchased
    >         & date of purchase.                                       """
    >     cur = conn.cursor()
    >     try:
    >         createTableQ = "create table "+stock.code+" (date varchar
    > PRIMARY KEY, recent_price float, recent_offer float, recent_bid float,
    > stock_volume double);"
    >         stockQuery   = "insert into "+stockTable+"
    > values(?, ?, ?, ?);"
    >         cur.execute(createTableQ)
    >         cur.execute(stockQuery,
    > [stock.code,stock.purchasePrice,stock.purchaseQuant,getDate()])
    >         conn.commit()
    >     except IOError or OSError:
    >         print "Table may already exist or bad SQLite connection."
    >         return False
    > 
    > def webFormat(URL):
    > 
    >     if (URL.startswith("http://")==False):
    >         URL = "http://"+URL
    > [/color]
    Better as:
    
         if not URL.startswith("http://"):
    
    The conditions of 'if' and 'while' statements don't need to enclosed in
    parentheses like in C, Java, etc.
    [color=blue]
    >     return URL
    > 
    > def getSource(URL):
    >     """ Retrieve HTML source code from website URL &
    >         save in sourceBuffer                       """
    > 
    >     try:
    >         URL = webFormat(URL) # make sure URL contains essential
    > "http://"
    >         sourceBuffer = urllib2.urlopen(URL)
    >         print '\nResponse code = ',sourceBuffer.code
    >         print 'Response headers = ',sourceBuffer.info()
    >         print 'Actual URL = ',sourceBuffer.geturl()
    >         sourceCode = sourceBuffer.read()
    >         sourceBuffer.close()
    >         return sourceCode
    > 
    >     except IOError:  # URLError
    >         print "Function Failed: Reasons could be invalid URL name \nOR
    > \nHTML protocol message transfer failure."
    >         return False # function failed
    > 
    > def getTargetText(targetStrtData, targetEndData, dataBuffer):
    >     """ Grabs target text that lies inside 'dataBuffer' string
    >         between targetStrtData & targetEndData                """
    > 
    >     try:
    >         result = dataBuffer.split(targetStrtData)
    >         result.pop(0)
    >         result = result[0].split(targetEndData)
    >         result.pop(1)
    >         print result
    >         return result
    >     except IOError:
    >         print "Function Failed: Reasons could be targetStrtData and/or
    > targetEndData is not present in dataBuffer."
    > [/color]
    You haven't given a return statement for when there's an error, so it'll
    return None. It's probably clearer if you write a function in Python
    either as a _function_ which _always_ returns a value or as a
    _procedure_ which _never_ returns a value.
    
    In Python the preference is for a function to raise an exception to
    indicate an error instead of returning a flag.
    [color=blue]
    > def getStockData(htmlText, selectedStock):
    >     """ Extract stock data(stock code,price,etc) from htmlText """
    >     try:
    >         # Here I extract my number data from HTML text
    >         tempList = []
    >         for string in htmlText:
    >             for i in string.split('>'):
    >                 for e in i.split():
    >                         if ('.' in e and e[0].isdigit()):
    >                             tempList.append(float(e))
    >                         elif (',' in e and e[0].isdigit() ):
    >                             # remove ',' chars
    >                             e = e.replace(',','')
    >                             tempList.append(float(e))
    > 
    >  
    > selectedStock.updateData(tempList[0],tempList[2],tempList[3],tempList[7])
    > 
    >     except IOError:  # is this the correct error I should be trying to
    > catch here??
    >         print "Function Failed: Reasons could be: sites HTML data has
    > changed. Consult author of program."
    >         return False
    > 
    > def createStockTracker(stockCode,stockPrice,stockQuant, stockList):
    >     """ Add a new stock to the database to track """
    >     newStock = stock()
    >     newStock.constructor(stockCode,stockPrice,stockQuant)
    >     stockList.append(newStock)
    >     return stockList
    > 
    > def writeStockToDatabase(conn, stock):
    >     """ Write ONLY this Stock's attributes to SQLite Database """
    > 
    >     cur = conn.cursor()
    >     date = getDate()
    > 
    >     tableName = stock.code
    >     stockquery = "insert into "+tableName+" values(?, ?, ?, ?, ?);"
    >     cur.execute(query,[date,stock.price[-1], stock.recentOffer[-1],
    > stock.recentBid[-1], stock.stockVol[-1]])
    >     conn.commit()
    > 
    > def writeAllToDatabase(conn, stockList):
    >     """ Enter recent Stock attributes into SQLite Database """
    > 
    >     cur = conn.cursor()
    >     date = getDate()
    > 
    >     for stock in stockList:
    >         tableName = stock.code
    >         stockquery = "insert into "+tableName+"
    > values(?, ?, ?, ?, ?);"
    >         cur.execute(query,[date,stock.price[-1],
    > stock.recentOffer[-1], stock.recentBid[-1], stock.stockVol[-1]])
    >         conn.commit()
    > 
    > ### Input Functions ###
    > def inputNewStock():
    >     """ """
    >     print "*Please note only an Australian Securities Exchange(ASX)
    > listed stock can be tracked in Version 1.0."
    >     badInput = True
    > 
    >     while (badInput == True):[/color]
    
    Better as:
    
         while badInput:
    [color=blue]
    >         try:
    >             code     = raw_input("Please enter the ASX code for the
    > stock you wish to track: ")[/color]
    
    If you assign to a name in a function then that name will be treated as
    a local name (variable) unless you say it's global in the function,
    therefore 'code', etc, won't been seen outside this function.
    [color=blue]
    >             price    = input("Please enter the individual stock value
    > for "+code+": ")
    >             quantity = input("Please enter the number/quantity of
    > stocks purchased: ")
    >             if (len(code)>3):
    >                 badInput = True
    >             else : badInput = False
    >             return True[/color]
    
    This will check the length, setting badInput accordingly, and then
    return True.
    [color=blue]
    >         except IOError:[/color]
    
    I don't see anything in the 'try' block that will raise IOError.
    [color=blue]
    >             if (raw_input("Incorrect input. Note: ASX code cannot be
    > more than 3 chars. Press 'x' to exit or anything else to try
    > again")=='x'):
    >                 return False
    >         badInput = True # this I am not sure if necessary to loop
    > correctly
    > [/color]
    You're not explicitly returning anything from the function when the loop
    exits, so it would return None.
    [color=blue]
    > 
    > ### Main program loop ###
    > def main():
    >     programEnd = False;
    >     dbLocation = "C:\Users\Sam\Desktop\StockApp/"[/color]
    
    If your string contains literal backslashes then use raw strings
    instead. Raw strings can end in a backslash, but that shouldn't matter
    in the script if you're joining paths together using os.path.join().
    [color=blue]
    >     dbName     = "stockData.db"
    >     stockTable = "stocks"
    > 
    >     conn = connectDatabase(dbLocation,dbName,stockTable)
    >     stockList = retrieveStockDatabase(conn,stockTable)
    > 
    >     for s in stockList:
    >         s.printStats()
    > 
    >     while (programEnd == False):[/color]
    
    Better as:
    
         while not programEnd:
    [color=blue]
    > 
    >         decision = input(menu) # Print Menu[/color]
    
    input() is often considered a bad function to use because it's
    equivalent to eval(raw_input()), so the user could enter any expression.
    It's better to use int(raw_input()) in this case and then catch the
    ValueError if what was entered isn't an int.
    [color=blue]
    > 
    >         if (decision==1):
    > 
    >             if not(inputNewStock()==False):[/color]
    
    A double-negative, equivalent to:
    
                 if inputNewStock() != False:
    
    It would be more Pythonic if you had inputNewStock() return the code,
    etc, or raise an exception if there was an error. You could then catch
    that exception in a 'try' block.
    [color=blue]
    >                 stockList =
    > createStockTracker(acode,price,quantity,stockList)
    >                 newStockDatabase(conn,stockTable,stockList[-1])
    >                 print("\n** New Stock **")
    >                 stockList[-1].printStats()
    >                 print "The stock "+code+" was successfully added to
    > our database. \nNow every time the program runs it will automatically
    > track this stock & obtain its stock attributes\n\n"
    >                 # TO DO:
    >                 # get new stock recent Data from internet etc.
    >                 # add stock data to data base;
    >         elif (decision==2):
    >             if (len(stockList)>0):[/color]
    
    Better as:
    
                 if stockList:
    [color=blue]
    >                 for Stock in stockList:
    >                     URL = ASXurl+Stock.code
    >                     sourceCode = getSource(URL)
    >                     targetData = getTargetText(target %
    > (Stock.code,Stock.code),"</tr>",sourceCode)
    >                     getStockData(targetData,Stock)
    >                     Stock.printStats()
    >                     #writeStockToDatabase(conn,Stock)
    >             else:
    >                 print "You must first identify a stock to follow.
    > \nPlease select option 1."
    >         elif (decision==3):
    >             print "Thank you for using Stock Program. Goodbye.\n"
    >             programEnd = True; # Exit program
    > 
    >     conn.close()
    >     return 0 # End program
    > [/color]
    'main' is called by the main program and its return value is never used,
    so just omit this return statement.
    [color=blue]
    > main()


    The recommended standard in Python is for names of classes to be
    CamelCase, names of constants to be UPPERCASE_WITH_UNDERSCORES, and
    names of everything else to be lowercase_with_underscores.
     
    MRAB, Mar 24, 2010
    #3
  4. On Wed, 24 Mar 2010 21:14:23 -0700, Tim Roberts wrote:

    > Jimbo <> wrote:
    >>
    >>class stock:
    >> code = ""
    >> purchasePrice = 0
    >> purchaseQuantity = 0
    >> price = [] # list of recent prices
    >> recentBid = [] # list of recent bids for stock
    >> recentOffer = [] # list of recent offers for stock
    >> stockVol = [] # list of stock quantity available on market

    >
    > Using lists as class variables is a very good way to create very
    > surprising bugs. Consider the following:

    [snip]


    Don't you think that the class attributes are *supposed* to be shared by
    all instances? In that case the behaviour you show is not a bug at all.


    --
    Steven
     
    Steven D'Aprano, Mar 25, 2010
    #4
  5. Steven D'Aprano a écrit :
    > On Wed, 24 Mar 2010 21:14:23 -0700, Tim Roberts wrote:
    >
    >> Jimbo <> wrote:
    >>> class stock:
    >>> code = ""
    >>> purchasePrice = 0
    >>> purchaseQuantity = 0
    >>> price = [] # list of recent prices
    >>> recentBid = [] # list of recent bids for stock
    >>> recentOffer = [] # list of recent offers for stock
    >>> stockVol = [] # list of stock quantity available on market

    >> Using lists as class variables is a very good way to create very
    >> surprising bugs. Consider the following:

    > [snip]
    >
    >
    > Don't you think that the class attributes are *supposed* to be shared by
    > all instances? In that case the behaviour you show is not a bug at all.


    Python's class attributes are indeed supposed to be shared - that's even
    the whole point of having class attributes.

    But this feature has proven to be confusing for newcomers that more
    often than not have previous exposure to OOPLs where you do "declare"
    your class "schema" at the class level (where Python defines class
    attributes).

    Now reread the OP's code, and you'll find out he's indeed yet another
    victim of this gotcha:

    """
    for row in cur.fetchall():
    newStock = stock()
    newStock.code = row[0]
    newStock.purchasePrice = row[1]
    newStock.purchaseQuantity = row[2]
    cur.execute(stockQuery,[newStock.code])
    for rw in cur.fetchall():
    newStock.price.append(rw[0])
    newStock.recentOffer.append(rw[1])
    newStock.recentBid.append(rw[2])
    newStock.stockVol.append(rw[3])
    stockList.append(newStock)
    """
     
    Bruno Desthuilliers, Mar 25, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xah Lee
    Replies:
    62
    Views:
    1,652
  2. Xah Lee
    Replies:
    61
    Views:
    1,100
  3. Replies:
    0
    Views:
    422
  4. Ian Kelly
    Replies:
    3
    Views:
    395
    Arnaud Delobelle
    Feb 16, 2012
  5. Xah Lee
    Replies:
    58
    Views:
    478
Loading...

Share This Page