Line edits at 0 when not used? PyQt - python

i'm in a situation where i take the user input and do some math operations.. The user selects an item from a combobox, and inputs a number in the line edit next to it. When he clicks ok, it returns (comboboxselectedvalue)+(lineeditvalue), it works, most of the time, my problem is, when the user leaves the lineedit in blank, it returns an error:
ValueError: invalid literal for int() with base 10: ''
cb1 = self.lineEdit.text()
zb1=self.comboBox.currentText()
az1 = int(cb1)
print(zb1+az1)
How can i set the value of line edits to 0 when nothing is typed in and left in blank? I have 20 line edits and 20 combo boxes..

Your code is going to raise an exception whenever the user enters anything that's not a number—including nothing at all.
The nicest way to handle this is by validating the entry (and pre-filling it with something valid, like 0), so they can't click OK with something invalid in the box.
But if you want to handle this in the "engine" code instead of in the GUI, you can; it just won't be as nice a user experience.
It sounds like what you want to do is treat an empty box as 0. What about a non-empty but non-numeric entry? Should that also be treated as 0? If so, this is easy; the exception already catches exactly what you want to catch, so you just need to handle it.
try:
az1 = int(cb1)
except ValueError:
az1 = 0
If, on the other hand, you want to treat non-numeric entries different from empty, it's a bit more complicated; the exception lumps them both in together, so you'd need an if test either instead of or in addition to the exception. If, say, you wanted non-numeric text to abort the program as it currently does, but an empty box to mean 0, you could write:
try:
az1 = int(cb1)
except ValueError:
if not az1:
az1 = 0
else:
raise
Or, more briefly:
az1 = int(cb1) if cb1 else 0

Related

Odoo Discard Change When an Exception Occurred

I need to discard the change user made when an exception occurred, to go back to the value when input is valid.
For example I have 2 field check_in & check_out as Date type. I need to check the check_in must be smaller than check_out. When the check_in is bigger than check_out, an exception dialog shows. When the user closes the exception dialog, I need to discard the change for check_in.
#api.onchange('check_in', 'check_out')
def validate_check_in(self):
for rec in self:
if rec.check_in > rec.check_out:
raise ValidationError("Not valid check in and check out")
I don't know the method of discarding the changes. However, I do have a workaround in case you haven't got one.
By using _origin, you can get the original values before the onchange is triggered. So, when the exception is going to occur, you can just set the value(s) back to its original state, which is almost similar to discard.
The code should be something like this.
#api.onchange('check_in', 'check_out')
def validate_check_in(self):
for rec in self:
if rec.check_in > rec.check_out:
rec.check_in = rec._origin.check_in # Added for the workaround
raise ValidationError("Not valid check in and check out")
If you don't like this solution, please wait a bit longer in case there's someone who knows how to discard because I also want to know that.

Try/Except statement for widget entry box

try:
float(self.entry_weight.get()) and int(self.entry_height.get())
self.get_bears()
except:
messagebox.showinfo("Number Error","Your weight and height must be a number!")
Hello,
This try/except statement doesn't seem to be working, when I input numbers into the entry boxes, and click the associated button, I only get the message box saying that my inputs are not numbers.
I have used print statements to make sure I am testing the right entry boxes and i am. When i test the type i get back as expected but surely if these string inputs are numbers, the try except statement should work. Any help would be great thanks.
Your try/except block covers too much territory. In addition to problems with input, it catches everything that could go wrong with get_bears. Additionally, and short-circuits so the second check is never made if weight is 0. You can use two try/except blocks to cover everything
try:
# validate input
float(self.entry_weight.get())
int(self.entry_height.get())
except ValueError:
messagebox.showinfo("Number Error","Your weight and height must be a number!")
return
try:
self.get_bears()
except:
messagebox.showinfo("Unhandled Error","Unknown error in program")
# log it somewhere
import traceback
traceback.print_exc()
# likely want to exit() because program is highly busted

How continue execute program after assertion in python?

I am learning Exception in python and i have some doubt:
Can we use any name as error in raise?
like i have read when you use raise you have to define error type so can't i use any stringname as Error? like SkienaError or i have to keep in mind all the error types and have to use only those Error type names ?
a=int(input())
if a!=10:
raise SkienaError
else:
print(a,"pp")
Second doubt is suppose i want user should input int but he input string so an assert pop up but i want program should continue without terminate and again ask for input until user give int type input , I don't want to use while loop here i want to know if it is possible with raise or assert in python ? like:
a=int(input())
assert type(a)==int
print(a,"hello")
So if user give str type input then is it possible program keep giving error and asking new input until input type is int.
In order to make your own exception, you'll have to create it.
e.g.
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
To continue execution after a thrown Exception, do it like this:
a = 5
try:
assert a == 5
except AssertionError as e:
print(e)
A try block will attempt to execute a block of code. If an exception occurs, it will execute the except block.
This might also work for your situation. The function Assert() prints a message sTxt in red color, if the Boolean input bCond is False and interpreter continues execution:
RED, END = '\033[91m', '\033[0m'
printRed = lambda sTxt: print(RED + sTxt + END)
Assert = lambda bCond=False, sTxt='': printRed(sTxt) if not bCond else None

Difference between raising exception and automatically causing an exception

Currently using the wxPython framework and my code looks like this:
Event bind:
self.frequency_grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_changed)
Function that handles changed cells:
def on_cell_changed(self, event):
self.current_grid = event.GetEventObject()
try:
new_value= self.get_cell_value()
if new_value < 0:
raise AttributeError
#allow the cell to update
except AttributeError:
event.Veto()
wx.MessageBox(_("Positive values only."), "", wx.OK|wx.ICON_WARNING)
except:
wx.MessageBox(_("Invalid value for cell."), "", wx.OK|wx.ICON_WARNING)
event.Veto()
The function get_cell_value() reads the value from the current cell and converts it to an integer simply by using int(). If the user enters a character like 'a' into the cell, obviously this function fails and the exception is raised. In this case the messagebox comes out telling the user the cell has an invalid value. This is what I call the automatically caused exception, and the final exception block is executed.
In the case of negative values, I manually raise an AttributeError (just wanted to see something different from ValueError which is what happens when user inputs characters).
In this case however, the wxPython sends the EVT_GRID_CELL_CHANGE event twice, so there must be something different about manually raised exceptions.
I've separately raised a ticket about the duplicated events at http://trac.wxwidgets.org/ticket/16333 but just trying to understand how the first scenario doesn't make wxPython send 2 events compared to the second scenario.
Don't use except: if you really want to catch any possible error(even system memory or anything else non-related).
To make your code look better, I'd suggest to cast value to int with try...except block, then check for negative values.
try:
value = int(text)
except:
return MessageBox('Enter digit')
if value < 0:
return MessageBox('Enter positive digit')
There is no difference in the Exceptions, but you are processing them in a different way, at a different place in the code.
I suspect it's the veto() call that causes the extra event. But why not validate the input in one place only? i.e have your get_cell_value() function should make sure it's an integer >0.
Also, this structure is both a recipe for circular events, and a painfully annoying UI. People should be able to make a typo and go back and correct it without an annoying dialog popping up.
Maybe provide an indicator of a problem, like making the cell background red, but only go the dialog route once the user tries to move on to the next step.
After a bit more tracing, I found that creating the MessageBox causes the EVT_GRID_CELL_CHANGING event to occur, which then leads to the EVT_GRID_CELL_CHANGED event to occur, which is why I saw duplicated events.
The reason why I did not see duplicated events during the entry of a character was because a Veto() was called in the event handler for the EVT_GRID_CELL_CHANGING if an int() conversion was invalid because my handler for that event gets the grid input and tries to convert it.
In conclusion, there is no difference in Python exception handling, but however, a better wxPython demo should be implemented to prevent the duplicated message box during the demo and show other users how to better use the grid mechanism.

What are exceptions in Python?

I've read three beginner-level Python books, however, I still don't understand exceptions.
Could someone give me a high level explanation?
I guess I understand that exceptions are errors in code or process that cause the code to stop working.
In the old days, when people wrote in assembly language or C, every time you called a function that might fail, you had to check whether it succeeded. So you'd have code like this:
def countlines(path):
f = open(path, 'r')
if not f:
print("Couldn't open", path)
return None
total = 0
for line in f:
value, success = int(line)
if not success:
print(line, "is not an integer")
f.close()
return None
total += value
f.close()
return total
The idea behind exceptions is that you don't worry about those exceptional cases, you just write this:
def countlines(path):
total = 0
with open(path, 'r') as f:
for line in f:
total += int(line)
return total
If Python can't open the file, or turn the line into an integer, it will raise an exception, which will automatically close the file, exit your function, and quit your whole program, printing out useful debugging information.
In some cases, you want to handle an exception instead of letting it quit your program. For example, maybe you want to print the error message and then ask the user for a different filename:
while True:
path = input("Give me a path")
try:
print(countlines(path))
break
except Exception as e:
print("That one didn't work:", e)
Once you know the basic idea that exceptions are trying to accomplish, the tutorial has a lot of useful information.
If you want more background, Wikipedia can help (although the article isn't very useful until you understand the basic idea).
If you still don't understand, ask a more specific question.
The best place to start with that is Python's list of built-in exceptions, since most you'll see derive from that.
Keep in mind that anybody can throw any error they want over anything, and then catch it and dismiss it as well. Here's one quick snippet that uses exceptions for handling instead of if/else where __get_site_file() throws an exception if the file isn't found in any of a list of paths. Despite that particular exception, the code will still work. However, the code would throw an uncaught error that stops execution if the file exists but the permissions don't allow reading.
def __setup_site_conf(self):
# Look for a site.conf in the site folder
try:
path = self.__get_site_file('site.conf')
self.__site_conf = open(path).read()
except EnvironmentError:
self.__site_conf = self.__get_site_conf_from_template()
Python's documentation: http://docs.python.org/2/tutorial/errors.html
For a high-level explanation, say we want to divide varA / varB. We know that varB can't equal 0, but we might not want to perform the check every time we do the division:
if varB != 0:
varA / varB
We can use exceptions to try the block without performing the conditional first, and then handle the behavior of the program based on whether or not something went wrong in the try block. In the following code, if varB == 0, then 'oops' is printed to the console:
try:
varA / varB
except ZeroDivisionError:
print 'oops'
Here is a list of exceptions that can be used: http://docs.python.org/2/library/exceptions.html#exceptions.BaseException
However, if you know how it may fail, you can just open a python console and see what exception is raised:
>>> 1 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
Exceptions are unexpected events that occur during the execution of a program. An exception might result from a logical error or an unanticipated situation.
In Python, exceptions (also known as errors) are objects that are raised (or thrown) by code that encounters an unexpected circumstance.
The Python interpreter can also raise an exception should it encounter an unexpected condition, like running out of memory. A raised error may be caught by a surrounding context that “handles” the exception in an appropriate fashion.
If uncaught, an exception causes the interpreter to stop executing the program and to report an appropriate message to the console.
def sqrt(x):
if not isinstance(x, (int, float)):
raise TypeError( x must be numeric )
elif x < 0:
raise ValueError( x cannot be negative )
Exceptions are not necessarily errors. They are things that get raised when the code encounters something it doesn't (immediately) know how to deal with. This may be entirely acceptable, depending on how you make your code. For instance, let's say you ask a user to put in a number. You then try to take that text (string) and convert it to a number (int). If the user put in, let's say, "cat", however, this will raise an exception. You could have your code handle that exception, however, and rather than break, just give the user a small message asking him to try again, and please use a number. Look at this link to see what I'm talking about: http://www.tutorialspoint.com/python/python_exceptions.htm
Also, you usually handle exceptions with a try, except (or catch) block. Example:
try:
integer = int(raw_input("Please enter an integer: "))
except Exception, exc:
print "An error has occured."
print str(exc)
Hope it helps!

Categories

Resources