Emikko29 Emikko29 - 5 months ago 47
Python Question

CS50 PSET7 Quote: 'NoneType' Error

I have been having some trouble with

/quote
in PSET 7 of CS50. Every time I go into the CS50 finance site, it returns:

AttributeError: 'NoneType' object has no attribute 'startswith'


I am not sure what it means, nor how to fix it. It seems to be automatically going to 'None' in the lookup function, but I am not sure why. If someone could help me, I would really appreciate it!

This is my quote part of application.py:

@app.route("/quote", methods=["GET", "POST"])
@login_required
def quote():
"""Get stock quote."""
if request.method == "POST":
symbol = request.args.get("symbol")
quote = lookup(symbol)
return render_template("quoted.html", name=quote)
else:
return render_template("quote.html")


This is my helpers.py, which is not supposed to be changed:

def lookup(symbol):
"""Look up quote for symbol."""

# reject symbol if it starts with caret
if symbol.startswith("^"):
return None

# reject symbol if it contains comma
if "," in symbol:
return None

# query Yahoo for quote
# http://stackoverflow.com/a/21351911
try:
url = "http://download.finance.yahoo.com/d/quotes.csv?f=snl1&s={}".format(symbol)
webpage = urllib.request.urlopen(url)
datareader = csv.reader(webpage.read().decode("utf-8").splitlines())
row = next(datareader)
except:
return None

# ensure stock exists
try:
price = float(row[2])
except:
return None

# return stock's name (as a str), price (as a float), and (uppercased) symbol (as a str)
return {
"name": row[1],
"price": price,
"symbol": row[0].upper()
}


Finally, this is my quote.html:

{% extends "layout.html" %}

{% block title %}
Quote
{% endblock %}

{% block main %}
<form action="{{ url_for('quote') }}" method="post">
<fieldset>
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="symbol" placeholder="symbol" type="symbol"text"/>
</div>
<div class="form-group">
<button class="btn btn-default" type="submit">Search for Quote</button>
</div>
</fieldset>
</form>
{% endblock %}

Answer Source

That error would occur when there's no "symbol" parameter in the request.

    symbol = request.args.get("symbol")
    quote = lookup(symbol)

Because it's not present, .get(...) will return None, and when you call lookup(None) it will try to run the following line, with symbol as None:

if symbol.startswith("^"):

Which means you're trying to do None.startswith(...), explaining the error you see.

You could check for the case where symbol is missing/None and display an error message.

    symbol = request.args.get("symbol")
    if symbol:
        quote = lookup(symbol)
        return render_template("quoted.html", name=quote)
    else:
        return render_template("missing_symbol.html")

Or you could just ignore it: if there's no symbol, the request is probably invalid, and you can accept that it causes an error.