Python Forum
ValueError: could not convert string to float: '' fron Entry Widget
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ValueError: could not convert string to float: '' fron Entry Widget
#1
Hello,

I have a simple program that takes user input from a tkinter entry widget and then converts the user input to a float for processing.

I am using Stringvar linked to the entry-textvariable and trace_add to monitor when the contents of the entry widget change to then call the function for processing

That is all working when a correct entry is passed, the issue I am seeing however is when the entry widget gains focus and the current contents are selected.

If I then type a new entry, effectively overwriting the contents of the entry widget, a call to the trace is made twice.

This first time containing '' which then gives the error ValueError: could not convert string to float: ''
A second call is then made with the values I have typed in the entry box and it all works fine.

I cannot figure out why Stringvar is set to '' when I enter a value into the entry widget.

Can anyone help me understand why this is happening and how to fix it?

Thanks.
Reply
#2
Show minimal reproducible example of your code
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
Next time post a short example that demonstrates the problem.

There is a big problem with your approach: A vast majority of strings raise an error when converted to float. Even typing in valid numeric strings can cause an error because the string is not always valid when typed in. For example, typing "-4" will raise an error when you press the "-" key.

Knowing that most strings will raise a ValueError, your trace function must allow for the error to occur without crashing the application.
import tkinter as tk

class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.var = tk.StringVar(self, "")
        self.var.trace_add("write", self.trace_func)
        tk.Entry(self, width=10, textvariable=self.var).pack(padx=10, pady=10)
        self.label = tk.Label(self, text="")
        self.label.pack(padx=10, pady=10)

    def trace_func(self, *_):
        try:
            self.label["text"] = str(float(self.var.get())**2)
        except ValueError:
            pass

Window().mainloop()
This works but notice that the displayed value changes each time you press a key. Do you really want that? When entering a number do you want to call your function each time a key is pressed, or do you want to wait for the entire number to be entered?

This example only updates the value when you press the enter key or the Entry loses focus.
import tkinter as tk

class FloatEntry(tk.Entry):
    """Custom Entry widget for float values.  Value updates
    when Return is pressed or widget loses focus.
    """
    def __init__(self, *args, command=None, **kwargs):
        self.var = tk.StringVar()
        super().__init__(*args, textvariable=self.var, **kwargs)
        self.command = command
        self.bind("<Return>", self._update_value)
        self.bind("<FocusOut>", self._update_value)
        self._value = 0
        self.var.set(str(self._value))

    @property
    def value(self):
        """Get current value."""
        return self._value

    @value.setter
    def value(self, value):
        """Set current value."""
        self.var.set(str(value))

    def _update_value(self, *_):
        """Validate input and call command function."""
        try:
            self._value = float(self.var.get())
            if self.command:
                self.command(self._value)
        except ValueError:
            # Revert to previous good value.
            self.var.set(str(self._value))

class Window(tk.Tk):
    """Display product of two numbers."""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.a = FloatEntry(self, command=self.update_display)
        self.b = FloatEntry(self, command=self.update_display)
        self.product = tk.Label(self, text="")
        self.a.pack(padx=10, pady=10)
        self.b.pack(padx=10, pady=10)
        self.product.pack(padx=10, pady=10)

    def update_display(self, *_):
        self.product["text"] = str(self.a.value * self.b.value)

Window().mainloop()
Reply
#4
Sorry i didnt include a sample as I didnt think it would help as you cant see the problem as such, as it happens when you select the contents of entry and type a new value. The code I have used I have replicated from others and videos as I am just starting out with python.

I have included a simple example of what I was doing that replicates the issue.

if I run this program and focus is set on the entry field and then type a number, in this example I pressed the number '6' the stringvar is updated twice, first with '' and i get the ValueError: could not convert string to float: '' and then as I would expect it is updated with '6'.

My program would only ever need positive numbers entered but the way I was doing it I now see was wrong

I have now updated my code now to reflect the way you have shown with a class and try/except and it works thank you.

However I am still interested to know why '' is being passed when I type '6' if youre able to shed any light on this?

Thanks for your help.

This is the sample code

import tkinter as tk

root = tk.Tk()

txt1 = tk.StringVar()
txt1.set("0")

def check(*args):
    print(f'*{type(txt1.get())} - {txt1.get()}*')

entr1 = tk.Entry(root, textvariable=txt1)
entr1.place(x=20,y=20)

txt1.trace_add("write", check)

root.mainloop()
Output:
*<class 'str'> - * *<class 'str'> - 6*
deanhystad write Mar-05-2024, 09:09 PM:
Please post all code, output and errors (in it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply
#5
Quote:Sorry i didnt include a sample as I didnt think it would help as you cant see the problem as such, as it happens when you select the contents of entry and type a new value.
Code is useful for a lot of things. It is a very accurate description of the problem. It provides insight into you level of knowledge. It establishes a starting point for future conversations. It is best if you can post code that others can run to see the problem.
import tkinter as tk

def check(*args):
    print(float(txt1.get()))

root = tk.Tk()
txt1 = tk.StringVar(root, "0")
txt1.trace_add("write", check)
entr1 = tk.Entry(root, width=10, textvariable=txt1)
entr1.pack(padx=50, pady=50)
root.mainloop()
And then add instructions for how to make the error occur.
Quote:To make the error happen, select the text in the entry and type in a digit. You should get an error like this:
Error:
File "..test.py", line 4, in check print(float(txt1.get())) ValueError: could not convert string to float: ''

To answer your question, you get "" because pasting (or typing) in an entry deletes any selected text before entering new text. When there is a selection, the entry gets written twice. You'll see this if you run your example and alternate between typing with or without selecting text in the entry.
Reply
#6
Fantastic thank you. I thought it would be something simple like the entry gets cleared first but didnt know how to prove it/find out for sure.

Sorry about all the formatting issue with my post.

Thanks for all your help.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] entry widget DPaul 5 1,543 Jul-28-2023, 02:31 PM
Last Post: deanhystad
  Get string from entry and use it in another script amdi40 1 1,414 Jan-26-2022, 07:33 PM
Last Post: Larz60+
  Tkinter Exit Code based on Entry Widget Nu2Python 6 3,021 Oct-21-2021, 03:01 PM
Last Post: Nu2Python
  method to add entries in multi columns entry frames in self widget sudeshna24 2 2,270 Feb-19-2021, 05:24 PM
Last Post: BashBedlam
  Entry Widget issue PA3040 16 6,884 Jan-20-2021, 02:21 PM
Last Post: pitterbrayn
  [Tkinter] password with Entry widget TAREKYANGUI 9 6,015 Sep-24-2020, 05:27 PM
Last Post: TAREKYANGUI
  [Tkinter] Get the last entry in my text widget Pedroski55 3 6,432 Jul-13-2020, 10:34 PM
Last Post: Pedroski55
  How to retreive the grid location of an Entry widget kenwatts275 7 4,643 Apr-24-2020, 11:39 PM
Last Post: Larz60+
  POPUP on widget Entry taratata2020 4 3,775 Mar-10-2020, 05:04 PM
Last Post: taratata2020
  [Tkinter] manipulation of string in Text widget Stauricus 2 3,054 Feb-17-2020, 09:23 PM
Last Post: Stauricus

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020