"ValueError: could not convert string to float" when converting input
Asked Answered
A

2

10

Recently I have been working on a code and got stuck for days on this error. Basically the program calculates how many calories you have to eat everyday. I have to take input from an entry and I don't know how to convert that input(it's a string by default) into a float to start using the numbers. I am using Python 3 with Tkinter.

Here is the code:

from tkinter import *

root = Tk()
root.geometry("1000x500")
root.resizable(FALSE, FALSE)
root.title("BMI Calculator")

def calc(args):

    def BMI_temp(args):
        print(str(boyage))
        BMI = IntVar()
        BMI = 66.5 + (13.75 * float(boykg)) + (5.003 * float(boycm)) - (6.755 * float(boyage))
        bmi_temp = Label(root, text="This is how many calories you have to eat if you have a non-active life: " + str(float(BMI)))
        bmi_temp.grid(row=3, sticky=W)

    def boy_age_fnct(args):
        boy_age_entry.focus_set()
        boy_cm_entry.delete(0, "end")
        boy_age.grid(row=2, sticky=W)
        boy_age_entry.grid(row=2, column=1)
        boy_age_entry.bind("<Return>", BMI_temp)

    def boy_cm_fnct(args):
        boy_cm_entry.focus_set()
        boy_kg_entry.delete(0, "end")
        boy_cm.grid(row=1, sticky=W)
        boy_cm_entry.grid(row=1, column=1)
        boy_cm_entry.bind("<Return>", boy_age_fnct)

    boy_kg_entry.focus_set()
    temp = boygirle.get()
    gender = temp.title()
    welcome.destroy()
    hello_lbl.destroy()
    boygirle.destroy()
    boygirlq.destroy()

    if gender[0] == 'B':
        boy_kg.grid(row=0, sticky=W)
        boy_kg_entry.grid(row=0, column=1)
        boy_kg_entry.bind("<Return>", boy_cm_fnct)

    boyage = boy_age_entry.get()
    boycm = boy_cm_entry.get()
    boykg = boy_kg_entry.get()

def hello(args):
    name_user = name_entry.get()
    name2 = name_user.title()
    name_entry.delete(0, "end")
    hello = "Hello " + name2 + "!"
    hello_lbl["text"] = hello
    hello_lbl.grid(row=2, sticky=W)
    btn_cont.grid(row=3, sticky=W)
    name.destroy()
    name_entry.destroy()
    btn_cont.focus_set()

def BMI():
    btn_cont.destroy()
    boygirlq.grid(row=3, sticky=W)
    boygirle.grid(row=3, column=0, ipadx=35)
    boygirle.bind("<Return>", calc)
    boygirle.focus_set()

welcome = Label(root, text="Hello! This is a BMR calculator. It tells you how many calories you have to eat!", font="System 14 bold")
name = Label(root, text="Please enter your name:", font="System 12")
hello_lbl = Label(root, font="System 14")
boygirlq = Label(root, text="Are you a boy or a girl?", font="System 12 bold")
boy_kg = Label(root, text="Please enter your weight(in kg):", font="System 12 bold")
boy_cm = Label(root, text="Please enter your height(in cm):", font="System 12")
boy_age = Label(root, text="Please enter your age(in years):", font="System 12")

btn_cont = Button(root, text="Continue", font="Helvetica 12", command=BMI, relief=RAISED)

boy_kg_entry = Entry(root, font="System 12", relief=SUNKEN)
boy_cm_entry = Entry(root, font="System 12", relief=SUNKEN)
boy_age_entry = Entry(root, font="System 12", relief=SUNKEN)
name_entry = Entry(root, font="System 12", relief=SUNKEN)
boygirle = Entry(root, font="System 12", relief=SUNKEN)
name_entry.bind("<Return>", hello)
name_entry.focus_set()

welcome.grid(row=0, columnspan=2, ipadx=200)
name.grid(row=1, sticky=W)
name_entry.grid(row=1, column=0)

root.mainloop()

I tried all the methods I found on the internet but nothing worked.

Alysaalyse answered 6/1, 2019 at 20:40 Comment(5)
That error is caused by calling float() on a value that cannot be converted to a float. If you look closely at the error message, it should display the bad value, i.e. something like ValueError: could not convert string to float: apple. If it just ends with float:, that means the input was blank.Anacoluthia
I understand and I know that. I think I should place the boyage boycm and boykg somewhere else but where. I know that the error is because the entry is not completed. What should I do?Alysaalyse
Your calc() function should specifically check each value beforehand, and exit if any of the values can't be converted to floats.Anacoluthia
Ok thank you I will try to fix itAlysaalyse
As explained in the answer, ValueError: could not convert string to float can occur when reading a dataframe from a csv file and casting types df = df[['p']].astype({'p': float}). If the csv was recorded with empty spaces, python will not recognize the space characters. You need to overwrite empty cells with NaN using df = df.replace(r'^\s*$', np.nan, regex=True)Bibliofilm
L
18

Probable cause: you forgot to fill out one field

Explanation

a float can be constructed from a str, it just has to have the right format. You should be able to convert strings that look like floats to floats by just using float(mystr).

Pay attention to:

  • No spaces (or non-digit characters)
  • Period (.) as decimal separator, not comma (,)
  • some special things are allowed (e.g. inf, 5e3, ...)

Most probably (if you didn't cut anything off your error message), you forgot to fill out one field and are thus trying to perform float('').

Some examples

>>> float('')  # probably your case
Traceback (most recent call last):
  File "<pyshell#74>", line 1, in <module>
    float('')
ValueError: could not convert string to float:
>>> float('1')
1.0
>>> float('1.0')
1.0
>>> float('no number')
Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    float('no number')
ValueError: could not convert string to float: 'no number'
>>> float('10e30')
1e+31
>>> float('inf')
inf
>>> float('123.456')
123.456
>>> float('123,456')  # , not allowed
Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    float('123,456')
ValueError: could not convert string to float: '123,456'
>>> float('123 456')  # no whitespace as separator
Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    float('123 456')
ValueError: could not convert string to float: '123 456'

Further thoughts

An alternative for getting the float values is asking for them in a popup window -- this can be done with tkinter.simpledialog.askfloat. This will return you a float directly and show an error message if the string entered could not be converted. But, it may also return None when the user clicks the "Cancel" button, so you might want to check the result before computing stuff.

Example:

import tkinter as tk
from tkinter.simpledialog import askfloat

def click():
    val = askfloat('Title', 'The prompt:')  # float or None (cancel)
    if val is not None:
        tk.Label(root, text=f'The value "{val}" is a valid float').pack()  # f-string, replace with `'The value "{}" is ...'.format(val)` if you get an error (Python < 3.6)

root = tk.Tk()
tk.Button(root, text='Click!', command=click).pack()
root.mainloop()

Edit:

If you keep the Entry widgets, you may want to catch the error and show the user a message. This can easily be done with tkinter.mesagebox, specifically of this case the showerror function.

Example:

import tkinter as tk
from tkinter.messagebox import showerror

def click():
    try:
        val = float(entry.get())
    except ValueError as e:
        showerror('Error title', 'The number could not be converted to float:\n'+str(e))
    else:
        entry.delete(0, tk.END)
        Label(root, text=val).pack()

root = tk.Tk()
entry = tk.Entry(root)
tk.Label(root, text='insert a float value below:').pack()
entry.pack()
tk.Button(root, text='and click!', command=click).pack()
root.mainloop()
Limpid answered 6/1, 2019 at 21:35 Comment(3)
Thank you very much. I know what I have to do.Alysaalyse
You're welcome. You may also want to look into tkinter.messageboxLimpid
This solved my problem. I'm pulling data from an API and it turns out that I was receiving a single '' empty string back that couldn't be converted. A quick try except bypassed it. Thanks so much!Criminality
R
0

people looking for pandas

df = pd.read_csv('./file.csv', decimal=',')

or

df = df.replace(",", '.', regex=True)
Rigidify answered 16/11, 2023 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.