Python Forum
ValueError: could not convert string to float: '' fron Entry Widget - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: ValueError: could not convert string to float: '' fron Entry Widget (/thread-41707.html)



ValueError: could not convert string to float: '' fron Entry Widget - russellm44 - Mar-04-2024

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.


RE: ValueError: could not convert string to float: '' fron Entry Widget - buran - Mar-04-2024

Show minimal reproducible example of your code


RE: ValueError: could not convert string to float: '' fron Entry Widget - deanhystad - Mar-04-2024

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()



RE: ValueError: could not convert string to float: '' fron Entry Widget - russellm44 - Mar-05-2024

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*



RE: ValueError: could not convert string to float: '' fron Entry Widget - deanhystad - Mar-05-2024

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.


RE: ValueError: could not convert string to float: '' fron Entry Widget - russellm44 - Mar-06-2024

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.