I'm trying to simplify the following:
if x < 0:
print('we don't do negative numbers')
else:
NORMAL CODE HERE
I recently learned of the assert command, and admire its ability to simplify my previous lines into:
assert x > 0, 'errorText'
NORMAL CODE HERE
I don't want errors to give a traceback, though. I only want that single line like the if/else gives.
Is there a way to get an assertionError to return single line like exceptions do, or do I really need to keep running if/else's everywhere?
The assert statement in Python is intended for debugging or for testing. It serves the purpose of halting execution of the program when the condition is not True. When debugging you can include these statements in your code to help track down errors. Then remove them once the bug is fixed. Using assert in production code is a bad idea.
As you have it written using assert, your program will terminate if x is less than zero and the code that follows will not run.
You should continue to use if/else method to provide the two desired code paths. One path to log that x is less than zero, the other path to execute the code in the block NORMAL CODE HERE.
If x should never be less than 0 at this point, and the remaining code must not be executed then you should raise an Exception that can be caught in the calling code.
def method_using_positive_numbers(x):
if x < 0:
raise ValueError("we don't do negative numbers")
NORMAL CODE HERE
Another option is to return from the method if the condition is not true.
def method_using_positive_numbers(x):
if x < 0:
print("we don't do negative numbers")
return
NORMAL CODE HERE
Related
The title might be misleading, so here is a better explanation.
Consider the following code:
def minimum_working_environment(r):
trial=np.arange(0,6)[::-1]
for i in range(len(trial)):
if r>trial[i]:
return i
return len(trial)
We see that if r is smaller than the smallest element of trial, the if clause inside the loop is never executed. Therefore, the function never returns anything in the loop and returns something in the last line. If the if clause inside the loop is executed, return terminates the code, so the last line is never executed.
I want to implement something similar, but without return, i.e.,
def minimum_working_environment(self,r):
self.trial=np.arange(0,6)[::-1]
for i in range(len(self.trial)):
if r>trial[i]:
self.some_aspect=i
break
self.some_aspect=len(self.trial)
Here, break disrupts the loop but the function is not terminated.
The solutions I can think of are:
Replace break with return 0 and not check the return value of the function.
Use a flag variable.
Expand the self.trial array with a very small negative number, like -1e99.
First method looks good, I will probably implement it if I don't get any answer. The second one is very boring. The third one is not just boring but also might cause performance problems.
My questions are:
Is there a reserved word like return that would work in the way that I want, i.e., terminate the function?
If not, what is the best solution to this?
Thanks!
You can check that a for loop did not run into a break with else, which seems to be what you're after.
import numpy as np
def minimum_working_environment(r):
trial = np.arange(0, 6)[::-1]
for i in range(len(trial)):
if r > trial[i]:
return i
return len(trial)
def alternative(r):
trial = np.arange(0, 6)[::-1]
for i in range(len(trial)):
if r > trial[i]:
break
else:
i = len(trial)
return i
print(minimum_working_environment(3))
print(minimum_working_environment(-3))
print(alternative(3))
print(alternative(-3))
Result:
3
6
3
6
This works because the loop controlling variable i will still have the last value it had in the loop after the break and the else will only be executed if the break never executes.
However, if you just want to terminate a function, you should use return. The example I provided is mainly useful if you do indeed need to know if a loop completed fully (i.e. without breaking) or if it terminated early. It works for your example, which I assume was exactly that, just an example.
Hello everyone I have my code almost done but I'm trying to add in some sort of check to avoid errors. But I'm not really understanding what statement would be better to use to test the code. I know there are a few options of either using a loop, if-statement, or try. But here is the code in regards to doing captcha. I need it to run the first set of code which if the captcha doesn't pop up I continue on. But if the captcha does pop up solve it then continue on.
Some times captcha doesnt appear and if I run the whole set of code I get an error because we are expecting captcha to pop up.
Or if the captcha does appear to solve it which would.
I would really appreciate any help please as I'm not sure the right statement to use.
try should be used when something would return an error and would otherwise cause your program to stop/crash. An example of this would be:
try:
import pandas
except:
print("Unable to import pandas. Module not installed")
In this example your program will attempt to import the pandas module. If this fails it will then print out a line of text and continue running.
if statements are used to decided when to do something or not based on the returned logic. The key difference is that logic IS returned and not an error.
if x > 10:
print("This is a large number")
else:
print("This is a small number")
With this example, if 'x' did not exist it would produce an error, no more code will be executed, and the program will crash. The main difference between IF and TRY is whether logic is returned as true/false or is something just plains fails.
With your specific example it is important to know if the captcha appearing or not will break your code. Does the logic boil down to captcha = false or does captcha not exist at all and logic fails entirely?
Q: How do you define sometimes captcha doesn't appear (1%, 20%, 50%, ...)?
A: Maybe 5% of the time captcha doesn't appear.
In this case, I prefer to use Exception handling: do stuff and if something goes wrong, fix it
try:
# > 95% of the time the code below works when the captcha appears
except SomeException:
# < 5% of the time the code is called when the captcha doesn't appear
IMHO, you have not really 2 different codes: you have one and a fallback solution, it's really different than:
if x % 2:
...
else:
...
I am doing a python course where they suggested a try and except block in a while loop in order to keep asking for input until the condition is satisfied. Intuitively I feel it is shorter to just call the function again in the "except" block like this:
def exceptiontest():
try:
print(int(input("number 1: "))+int(input("number 2:")))
except:
print("a mistake happened")
exceptiontest()
exceptiontest()
When asking on the forum on the course I got the reply that it is not the same. I am a bit confused now. Anyone that can clarify for me? Thanks in advance!
Calling the function in the except will eventually raise a RecursionError: maximum recursion depth exceeded error if you keep entering bad inputs. Generally must humans won't be entering that many bad data to hit the error before they give up, but you are unnecessarily putting function calls on a stack.
A while loop is better since it's one function call, waiting for a valid input. IT doesn't waste any more resources than it needs.
while loop, for two reasons
it's clearer to read: while not success, try again
recursion is not free. It leaves the previous function stack open. it could run out of memory (probably won't, in this case, but in principle, avoid it)
Another reason to use the while loop which has not yet been mentioned is that you could leverage the assignment expressions coming with Python 3.8.
The function add encapsulates getting two numbers and trying to add them.
def add():
'try to add two numbers from user input, return None on failure'
x = input('number 1: ')
y = input('number 2: ')
try:
return float(x) + float(y)
except TypeError, ValueError:
return None
The following while loop runs as long as there is no result.
while (result := add()) is None:
print('you made a mistake, make sure to input two numbers!')
# use result
An Emirp is a prime number whose reversal is also a prime number. For example, 17 is a prime and 71 is a prime, so 17 and 71 are emirps.
The following code compiles and accepts input. The input validation is correct but the program keeps running and does not output anything. I also wanted to know how it's possible to find errors in python. Please ignore indentation errors if there are any.
class negerror(UserWarning):
pass
while True:
prompt = input('Please enter a positive number: ')
try:
number=int(prompt)
if number<=0:
raise negerror
break
except ValueError:
print('You did not enter an integer. Please try again. ')
except negerror:
print('You entered a negative number. Please make sure to enter a positive number')
def isPrime(value):
count=0
for i in range(1,value+1):
if value%i==0:
count=count+1
if count<=2:
return True
else:
return False
def reverse(value):
val=str(value)
val=val[::-1]
val=int(val)
return val
Test=2
countemirps=0
numberinoneline=0
while countemirps<number:
if isPrime(Test) and isPrime(reverse(Test)):
print('%6s'%Test, end = ' ')
countemirps=countemirps+1
Test=Test+1
numberinoneline=numberinoneline+1
if numberinoneline%5==0:
print('\n')
Your isPrime function is off. It counts the number of divisors of value and stores it in variable count. However, you return True if count>2 and False otherwise. It should be the other way around: a prime number has two divisors and composite numbers have more then two. So change the test to count <= 2. Even better and more pythonic, replace the last lines of that function with
return count <= 2
or perhaps
return count == 2
Do you see why that works?
(I see that you have now corrected this error and edited your question but the program still does not work.)
Another error is that in your main loop you have the test
if isPrime(Test) and isPrime(reverse(Test)):
If that test is passed, you print the number and update your variables including Test--all is well. However, if the test fails you do nothing, and in particular the value of Test is not changed. The loop repeats and you do exactly the same test, and nothing changes. The program is stuck in an infinite loop.
You can fix this by moving the line that updates Test out of the if test and place it at the end of the loop so it is executed on each loop. Your loop then becomes
while countemirps<number:
if isPrime(Test) and isPrime(reverse(Test)):
print('%6s'%Test, end = ' ')
countemirps=countemirps+1
numberinoneline=numberinoneline+1
if numberinoneline%5==0:
print('\n')
Test=Test+1
When I test your program now, it seems to work.
There may be other errors as well that I do not see. You should test function isPrime separately from the rest of your code. When that works well, then test function reverse. Then test sections of your code. Running your code all at once makes it difficult to localize and find errors.
Finally, you ask "how it's possible to find errors in Python". This is too broad a question for this site--you should read a book chapter or a tutorial on debugging. But in brief, there are two main approaches for beginners. The first is to liberally put print statements in your code, showing the flow of the program execution and the values of your key variables. If you had place the statement
print(Test)
at the beginning of your loop, you would have seen that the loop was repeating indefinitely and the value of Test was not changing. When the errors seem to be gone, you can remove or comment-out the print statements. Logging can do this a bit more easily
Another, better approach is to use a debugger. I do most of my Python programming in Spyder, a development environment which includes a debugger. I used that to execute your program one line at a time, and one window in Spyder showed my the values of your variables. There also are debuggers that work outside a development environment. I encourage you to find, learn, and use an Integrated Development Environment that includes a debugger. Spyder is a free, excellent one that specializes in scientific programming. I use it for my mathematics programming.
I am aware of a few ways to terminate a python script but here I am looking for a good and robust code design (sort of a recommended way to do this).
Most of my code is written in functions that are called from the main function.
I'd like to know what'd be the most recommendable way to stop running a python script/program from a given function (called from main) and give a message error to the user.
Example of my current design (please comment on better practices if have some ideas):
import sys
def run_function(x):
if x == 4:
print 'error, x cannot be 4'
sys.exit(0)
else:
print 'good x'
return 0
def main():
x=4
run_function(x)
return 0
Simply print the message, then use sys.exit() to end the program. The argparse module uses a utility function (adjusted to be more or less stand-alone):
def exit(status=0, message=None):
if message:
_print_message(message, sys.stderr)
sys.exit(status)
where _print_message() writes the message to the designated file object, here sys.stderr; basically just using print.
In your example, I would suggest that you raise error from the functions and only call the exit in __main__. The message will be passed using raise. Example:
import sys
def run_function(x):
if x == 4:
raise ValueError('error, x cannot be 4')
else:
print 'good x'
return 0
def main():
x=4
run_function(x)
return 0
if __name__ == "__main__":
try:
main()
except ValueError as e:
sys.exit(e)
This way, your function indicate that it received a wrong value, and it is the caller that decide to call a sys.exit based on the error.
A little more detail on the sys.exit:
The optional argument arg can be an integer giving the exit status
(defaulting to zero), or another type of object. If it is an integer,
zero is considered “successful termination” and any nonzero value is
considered “abnormal termination” by shells and the like. Most systems
require it to be in the range 0-127, and produce undefined results
otherwise. Some systems have a convention for assigning specific
meanings to specific exit codes, but these are generally
underdeveloped; Unix programs generally use 2 for command line syntax
errors and 1 for all other kind of errors. If another type of object
is passed, None is equivalent to passing zero, and any other object is
printed to stderr and results in an exit code of 1. In particular,
sys.exit("some error message") is a quick way to exit a program when
an error occurs.
Firstly, you might want to change your exit code when encountering an error. exit(0) normally means the process has terminated without errors. Then why are you returning something in your run_function, when you're not even checking it afterwards (in the else branch, I mean)?
Other than that, I don't see any questions here to be answered.