Full script here: http://pastebin.com/d6isrghF
I'll admit I'm very new to Python so please forgive my stupidity if this is an easy question to answer. The section in question is this:
sourcePath = jobPath
while os.path.basename(sourcePath):
if os.path.basename(os.path.dirname(sourcePath)).lower() == category.lower():
break
else:
sourcePath = os.path.dirname(sourcePath)
if not os.path.basename(sourcePath):
print "Error: The download path couldn't be properly determined"
sys.exit()
jobPath is being fed to the script from sabnzbd and is:
/mnt/cache/.apps/sabnzbd/complete/name.of.folder
category is:
tv
So I guess my question is: why is this failing with the error?
Why it does not work
Your code cannot work because while is executed until os.path.basename(sourcePath) is not evaluated to True, then if statement is called, which (because it looks like: if not os.path.basename(sourcePath)) is obviously evaluated as True and thus the message (your "error") is shown:
Annotated source code
sourcePath = jobPath
# This is executed until os.path.basename(sourcePath) is evaluated as true-ish:
while os.path.basename(sourcePath):
if os.path.basename(os.path.dirname(sourcePath)).lower() == category.lower():
break
else:
sourcePath = os.path.dirname(sourcePath)
# Then script skips to the remaining part, because os.path.basename(sourcePath)
# has been evaluated as false-ish (see above)
# And then it checks, whether os.path.basename(sourcePath) is false-ish (it is!)
if not os.path.basename(sourcePath):
print "Error: The download path couldn't be properly determined"
sys.exit()
When (and why) it sometimes works
It sometimes works only because category is found in the path, which means while loop will be exited (using break) even despite still meeting criteria (the condition after while keyword: os.path.basename(sourcePath)). Because the condition from while loop is still met (we exited the loop even though it was met), the next statement's condition (not os.path.basename(sourcePath)) is no longer met and the message ("the error") is not printed.
Possible solutions
I believe one of the solutions is to add a counter to your code, that will print the error only if in specific number of iterations you will not be able to find what you needed. You can also try to catch "too many recursions" exception (if you will use recursion, of course, but the error will be like this: RuntimeError: maximum recursion depth exceeded).
However, you should redesign it rather to meet your own needs.
Related
I am fairly new to coding so please bear with me.
If you look at the image, I have 3 workers and 3 stations where true means that the worker is trained for the station and false means that the worker is not.
Now, what my code does is that, it chooses a random choice between all the true for the first station. Then it eliminates that option for the next station and then chooses a random choice from all the Trues for the next station and so on.
Now, there is a possibility that, because of random choices, the code has no options left as all the true have been used before and the rest are false. In this case, it gives me an error "Cannot choose from an empty sequence".
Now, what I want is that, I want to have a way (maybe an if statement) which says if 'error occurs' then rerun the whole code. So, this way I would end up not getting an error as it would rerun until I do not get an error. I am not sure if this is even possible in python.
Thanks in advance.
You can Use try / except like this:
try:
random.choice
except:
pass
So if try section runs without errors, random.choice will be execute but if occur an error, except section execute and it just pass and your code continues.
I am trying to open an Excel file and to take the columns according to the names (headings). If it doesn't find those headings, I want the script to stop and display a message that the column was not found.
I first assign the current numbers to the columns with those names, and then I search for the name in the headings to make sure there were no columns inserted in between that will alter the column numbers. If the number is not the same, it will take whatever column number the name is in.
I have been trying to put an "else" under the "elif" and asking it to print an error and then I put a "break". The problem is that it doesn't stop the script if a column name is not found, it just takes the default assignment. I do understand why that break won't stop the whole script, but I don't know how to put it in order to stop it. The code is a bit more complex than just this, but I hope this will give a good understanding.
I also tried removing the default assignment but then it says that it can't find "i" so it gives me an error.
I would really appreciate some help.
Code:
colTPNumber = 2
colTDNumber = 3
rows = sheet.iter_rows(min_row=1, max_row=1)
firstRow = next(rows)
for i in firstRow:
if str(i.value) == "TP":
colTPNumber = i.column
elif str(i.value) == "TD":
colTDNumber = i.column
else:
print ("Column name not found")
break
break exits the loop, not the whole program.
Use exit() or sys.exit() (don't forget to import sys for the second option) to exit the program
Example:
import sys #unnessary if you're using exit() only
colTPNumber = 2
colTDNumber = 3
rows = sheet.iter_rows(min_row=1, max_row=1)
firstRow = next(rows)
for i in firstRow:
if str(i.value) == "TP":
colTPNumber = i.column
elif str(i.value) == "TD":
colTDNumber = i.column
else:
print ("Column name not found")
#break
sys.exit()
#OR
exit()
Some more info:
You can also use quit()
quit() raises the SystemExit exception behind the scenes.
Furthermore, if you print it, it will give a message:
>>> print (quit)
Use quit() or Ctrl-Z plus Return to exit
This functionality was included to help people who do not know Python. After all, one of the most likely things a newbie will try to exit Python is typing in quit.
Nevertheless, quit should not be used in production code. This is because it only works if the site module is loaded. Instead, this function should only be used in the interpreter.
exit() is an alias for quit (or vice-versa). They exist together simply to make Python more user-friendly.
Furthermore, it too gives a message when printed:
>>> print (exit)
Use exit() or Ctrl-Z plus Return to exit
However, like quit, exit is considered bad to use in production code and should be reserved for use in the interpreter. This is because it too relies on the site module.
sys.exit raises the SystemExit exception in the background. This means that it is the same as quit and exit in that respect.
Unlike those two however, sys.exit() is considered good to use in production code. This is because the sys module will always be there.
os._exit exits the program without calling cleanup handlers, flushing stdio buffers, etc. Thus, it is not a standard way to exit and should only be used in special cases. The most common of these is in the child process(es) created by os.fork.
Note that, of the four methods given, only this one is unique in what it does.
Summed up, all four methods exit the program. However, the first two are considered bad to use in production code and the last is a non-standard, dirty way that is only used in special scenarios.
So, if you want to exit a program normally, go with the third method: sys.exit.
Or, even better in my opinion, you can just do directly what sys.exit does behind the scenes and run:
raise SystemExit
This way, you do not need to import sys first.
However, this choice is simply one on style and is purely up to you
Adapted from: https://www.edureka.co/community/16988/python-exit-commands-why-so-many-and-when-should-each-be-used
More info on sys.exit():
sys.exit([arg])
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
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.
Since exit() ultimately “only” raises an exception, it will only exit the process when called from the main thread, and the exception is not intercepted.
Changed in version 3.6: If an error occurs in the cleanup after the Python interpreter has caught SystemExit (such as an error flushing buffered data in the standard streams), the exit status is changed to 120.
From https://docs.python.org/3/library/sys.html
Give the variables invalid default values, so you can check them after the loop.
Then you can call exit() if they're not set correctly, this will terminate the entire script.
colTPNumber = None
colTDNumber = None
rows = sheet.iter_rows(min_row=1, max_row=1)
firstRow = next(rows)
for i in firstRow:
if str(i.value) == "TP":
colTPNumber = i.column
elif str(i.value) == "TD":
colTDNumber = i.column
if colTPNumber is None or colTDNumber is None:
print("Column name not found")
exit(1)
See Terminating a Python script
Try using exit() instead of break. break ends a loop, but exit() actually exits your program.
I guess I'm not the first asking this question, but I haven't found a solution that I could use/understand yet. And the issue is probably not as simple as i first expected.
I think it can be boiled down to two general questions:
1) Is there a way to avoid Python to stop when an error occur and just jump on to the next line of code in the script?
2) Is there a way to make Python execute a line of code if an error occurs? Like, if error then...
My concrete problem:
I have a very large program with a lot of functions and other stuff, which would take forever to adjust individually by using "try" for example (if i understand it correctly)
My program run as a large loop that gather information and keeps running. This means that it does not really matter to me, that my program fails multiple time as long as it keeps running. I can easily handle that some of the information is with error and would just like my program to take a note of it and keep going.
Is there a solution to this?
As you rightly pointed out, the try/catch block in Python is by far your best ally:
for i in range(N):
try: do_foo() ; except: do_other_foo()
try: do_bar() ; except: do_other_bar()
Alternatively, you could also use, in case you didn't need the Exception:
from contextlib import suppress
for i in range(N):
with suppress(Exception):
do_foo()
with suppress(Exception):
do_bar()
Your only possibility is to rely on the try/except clause. Keep in mind that the try/except may use also finally and else (see documentation:
try:
print("problematic code - error NOT raised")
except:
print("code that gets executed only if an error occurs")
else:
print("code that gets executed only if an error does not occur")
finally:
print("code that gets ALWAYS executed")
# OUTPUT:
# problematic code - error NOT raised
# code that gets executed only if an error does not occur
# code that gets ALWAYS executed
or, when an error is raised:
try:
print("problematic code - error raised!")
raise "Terrible, terrible error"
except:
print("code that gets executed only if an error occurs")
else:
print("code that gets executed only if an error does not occur")
finally:
print("code that gets ALWAYS executed")
# OUTPUT:
# problematic code - error raised!
# code that gets executed only if an error occurs
# code that gets ALWAYS executed
I urge to point out, by the way, that ignoring everything makes me shiver:
you really should (at least, more or less) identify which exception can be raised, catch them (except ArithmeticError: ..., check built-in exceptions) and handle them individually. What you're trying to do will probably snowball into an endless chain of problems, and ignoring them will probably create more problems!
I think that this question helps to understand what a robust software is, meanwhile on this one you can see how SO community thinks python exceptions should be handled
I have a piece of coding that is most basically a quiz. I had error handling so that if someone pressed a letter or anything other than a number, it would carry on with the quiz instead of letting the person attempt another question. (For example, if question 5 was 2+3 and they entered t, then it would carry on and not give them a different question for question 5).
I tried to update the coding, so it would loop:
def random_question():#defines function to get random question
count = 0#equates count to 0
for number in range (0,10):#makes the code generate the question 10 times
try:#the code makes it so the computer tries one thing and is the beggining
questionList = [random_sum,random_subtraction,random_times]#puts functions in a list to be called on
randomQuestion = random.choice(questionList)#calls on the list to generate the random questions
randomQuestion()#calls on variable
except ValueError:#if there is a value error or a type error it will notice it and try to stop it
print ("Please enter a number")#prints out the statement if there is a type error or a value error
else:
break
random_question()#calls on the function random_question
However, it comes up with a syntax error, and highlights the 'except' part next to the ValueError.
Any help as to why this is would be much appreciated.
Your except statement should have the same indention as your try statement. In your sample code it is indented an extra tab which would cause that error.
Python takes indention seriously and it is often the culprit. I'm unclear if your def line is a place holder or if this code is part of it, but if this code is part of the function definition you have other indention issues to worry about.
I'd suggest going through it carefully and making sure everything is lined up properly. The basic rule of thumb is, if something is part of something else, it is indented under it.
def something():
step 1
step 2
if (condition):
the true thing
else:
the false thing
while (something):
repeat something
this is not part of the function anymore
I am learning Python and have stumbled upon a concept I can't readily digest: the optional else block within the try construct.
According to the documentation:
The try ... except statement has an optional else clause, which, when
present, must follow all except clauses. It is useful for code that
must be executed if the try clause does not raise an exception.
What I am confused about is why have the code that must be executed if the try clause does not raise an exception within the try construct -- why not simply have it follow the try/except at the same indentation level? I think it would simplify the options for exception handling. Or another way to ask would be what the code that is in the else block would do that would not be done if it were simply following the try statement, independent of it. Maybe I am missing something, do enlighten me.
This question is somewhat similar to this one but I could not find there what I am looking for.
The else block is only executed if the code in the try doesn't raise an exception; if you put the code outside of the else block, it'd happen regardless of exceptions. Also, it happens before the finally, which is generally important.
This is generally useful when you have a brief setup or verification section that may error, followed by a block where you use the resources you set up in which you don't want to hide errors. You can't put the code in the try because errors may go to except clauses when you want them to propagate. You can't put it outside of the construct, because the resources definitely aren't available there, either because setup failed or because the finally tore everything down. Thus, you have an else block.
One use case can be to prevent users from defining a flag variable to check whether any exception was raised or not(as we do in for-else loop).
A simple example:
lis = range(100)
ind = 50
try:
lis[ind]
except:
pass
else:
#Run this statement only if the exception was not raised
print "The index was okay:",ind
ind = 101
try:
lis[ind]
except:
pass
print "The index was okay:",ind # this gets executes regardless of the exception
# This one is similar to the first example, but a `flag` variable
# is required to check whether the exception was raised or not.
ind = 10
try:
print lis[ind]
flag = True
except:
pass
if flag:
print "The index was okay:",ind
Output:
The index was okay: 50
The index was okay: 101
The index was okay: 10