Forums

Convert str to float

I'm working on pulling some stock quotes and I'm having trouble converting the string it returns to a float.

Here is the code:

a = urllib.urlopen("http://finance.yahoo.com/q;_ylt=AhPWqUh6C8Mq67175Sg2SyfxVax_;_ylu=X3oDMTFidmlsaThhBHBvcwMxMgRzZWMDeWZpU3ltYm9sTG9va3VwUmVzdWx0cwRzbGsDc3NubGY-?s=SSNLF")
b = a.read()
regex = '<span id="yfs_l84_ssnlf">(.+?)</span>'
pattern = re.compile(regex)
price = re.findall(pattern, str(b))
price = price[0]

@app.route('/test') 
def test():
    return price

Any help would be greatly appreciated, thank you!

[edit by admin: formatting]

If you run that code line by line in a Python console, you'll see that the variable price winds up being set to something like "1,400.00". Normally you can convert a string into a float in Python just by doing something like float(price), but that won't work here because of the comma.

You could just hack it to remove the comma, for example by doing float(price.replace(",", "")), or you could use the locale module to parse the number (which would be better).

But I think the best option would be to use Yahoo's API rather than hitting their web page and trying to extract the price from something that's meant for human (as opposed to programmatic) consumption.

You can manually access the Yahoo API directly and write your own code to make queries and parse responses -- or you can use ystockquote, which is a useful Python package for doing that.

Here's what I did to try it out:

In a bash console:

$ pip install --user ystockquote

In a Python console:

>>> import ystockquote
>>> pystockquote.get_price("SSNLF")
'1400.00'
>>> float(ystockquote.get_price("SSNLF"))
1400.0

That's a great solution, and it works in bash, but why I try to pass the variable to get returned to the page I get the internal error. It works as a string, but if I convert to a float it throws that error.

What's the error message?

Just to be clear -- you may just see an unhelpful error message on the web page itself, but if you look into the error log (linked from the "Web" tab) you should get something more helpful.

2014-07-19 22:34:06,915 :Exception on /test [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1687, in wsgi_app
     response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1361, in full_dispatch_request
    response = self.make_response(rv)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1450, in make_response
    rv = self.response_class.force_type(rv, request.environ)
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/wrappers.py", line 711, in force_type
    response = BaseResponse(*_run_wsgi_app(response, environ))
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/test.py", line 818, in run_wsgi_app
    app_iter = app(environ, start_response)
TypeError: 'float' object is not callable

[edit by admin: formatting]

Hmm. I think that might be because you're returning the price as a float from the view, and then Flask is getting confused and trying to call it as a function. Try replacing

@app.route('/test') 
def test():
    return price

With something like this:

@app.route('/test') 
def test():
    return str(price)

...or...

@app.route('/test') 
def test():
    return "The price is %s" % (price,)

So, this is how I understand it, flask will only return it as a string, so I need to make modifications then convert back to a string for the output?

Also, thank you so much for your help!

That's what I'm thinking. Normally a Flask view would return a string or some kind of response object. Try returning it as a string from the view (like the first option I gave), and if that works then we have a solution :-)