Python output repeats even though it should break - python

I have a script that is using OpenCV to find faces and if a face is not found it outputs "No faces found" but it never does anything else. It should look back up and ask for another image. Can anyone tell me why it just prints "No faces found" until I press CTRL+C?
def Crop(
imagePattern,
boxScale,
outputimg,
padding,
):
happy = True
imgList = glob.glob(imagePattern)
while happy:
if len(imgList) <= 0:
return
else:
for img in imgList:
pil_im = Image.open(img)
cv_im = pil2cvGrey(pil_im)
faces = DetectFace(cv_im, faceCascade)
if faces:
n = 1
for face in faces:
croppedImage = imgCrop(pil_im, face[0],
padding, boxScale=boxScale)
(fname, ext) = os.path.splitext(img)
fname = os.path.basename(fname)
croppedImage.save(outputimg + '\\' + fname
+ ' -c' + ext)
n += 1
print 'Cropping:', fname
else:
print 'No faces found:', img
break
# Verify image
# savedPath = outputimg + '\\' + fname + ' -c' + ext
# verify = cv2.imread(savedPath, 0)
# cv2.imshow('Saved Image', verify)
print 'Please open the file manually to view for now'
print 'Are you happy with the final crop?'
happyTest = raw_input('Enter y or n: ')
happyTest = happyTest.strip()
if happyTest == 'y':
happy = False
elif happyTest == 'n':
padding = int(raw_input('Enter crop padding:'))
else:
print 'Not a valid input'
print 'Do you have more pictures to take?'
again = raw_input('Enter y or n: ')
if again == 'y':
Webcam(webcam, padding, boxScale)
else:
print 'Closing application'
time.sleep(3)
raise SystemExit
Sorry for the confusion, I had a bad copy/paste due to me using tabs for my code.
EDIT:
Thank you for letting me know about the mixing tabs and spaces but my issue is still the same. It also does not matter if I use a break or a continue. Do I need to use recursion and call the function again?

You are using a break statement, which halts the for loop completely.
Instead, use a continue statement there to skip the current image and move on to the next one within the for loop.
Read more about break and continue here
Also, You are using tabs and spaces togather, which is causing the indentation of the blocks to be misaligned. While they look as if they are aligned all right, you will have nightmares debugging tab errors, so just change your editor settings to use a tab as 4 whitespaces.
EDIT
There are multiple issues in your code:
You are checking for len(imgList)<=0 which is redundant as has already been pointed out in other answer.
The happytest value that you take is taken for every img in imglist, yet only the one entered on the last run will affect the value of the happy variable.
Because of #2 above, I am inclined to think that your original intent was to stop at any run during which the value of happy was False, which is definitely not happening right now.
You are using capital letters and camel case both to begin the name of some functions and I am having a hard time figuring if something is a public class or another function.
There are multiple external functions being referenced within the code, but I have not much clue of what they are supposed to do, and whether they actually do whatever they are supposed to do.

I don't know if this is the problem, but it is how you posted it anyway: Your commands after the else statement are not indented. Shouldn't it have given you an error?

The break you have coded breaks out of the for img in imgList: loop, not the while happy: loop. And since the code you use to ask the user if the cropping is satisfactory, is inside that loop (and after the break), it never gets reached (and thus happy can never be set False).

You have an extar break on your code -this version should work:
for img in imgList:
pil_im=Image.open(img)
cv_im=pil2cvGrey(pil_im)
faces=DetectFace(cv_im,faceCascade)
if faces:
n=1
for face in faces:
croppedImage=imgCrop(pil_im, face[0], padding, boxScale=boxScale)
fname,ext=os.path.splitext(img)
fname = os.path.basename(fname)
croppedImage.save(outputimg + '\\' + fname + ' -c' + ext)
n+=1
print 'Cropping:', fname
else:
print 'No faces found:', img
So, while it is true on the other answers and comments that you shpould not have the "break" inside the elsestatement - the problem you put forward in your question happens because you have that break at all: if the code reach that else block, it will just break out of the for img in imgList: loop and process nothing further.
besides that, I have fixed two other things in this code:
indentation - in Python it is serious business, not "what works is fine". The recomendation is to use 4 spaces per block nesting - no more, no less, and never, never mix tabs and spaces. You have to configure that on your code editor preferences.
The other part of your code that is alien to Python is the verification prior to the loop
if len(imgList)<=0: that is complettly superfluous in Python (not to mention the <= part): if the list lenght is zero (it can't be negative), the forstatement will try to pick the first item, and since it does not exist, the program will simply continue after the for block. Each level of indentation you reduce in your code is a bonus in readability. (The Zen of Python even reads "Flat is better than nested"). On the other hand, if in some other part of the code you really have to check if the lsit is empty,just do if imgList:, as sequences in Python have the nice property of having a False boolean value if they are empty, and True otherwise.

Related

Running the same program until condition satisfied

I am trying to create a small program that searches a folder of images, chooses one, checks its size and finishes if the chosen image is at least 5KB. If it is not then I need it to loop back to the choosing step (and then the size check, and so on..)
I am using functions for the choosing and the size-check but when I try to use them in a while loop I get all sorts of indentation errors and now I'm very confused. I've commented the section where I was using the function, but really I guess I want the whole thing to loop back, to the comment at the top..
Here's my code -
#CHOOSE POINT
def chosen():
random.choice(os.listdir(r"/Users/me/p1/images"))
def size():
os.path.getsize(r"/Users/me/p1/images/"+chosen)
thresh = 5000
while size < thresh:
print(chosen + " is too small")
# loop back to CHOOSE POINT
else:
print(chosen + " is at least 5KB")
Am I thinking about this all wrong? Will using the function in my while-loop do what I want? What's the best way to achieve what I'm trying to do? I'm quite new to this and getting very confused.
The first thing to realise is that code like this:
def chosen():
random.choice(os.listdir(r"/Users/me/p1/images"))
is only the definition of a function. It only runs each time you actually call it, with chosen().
Secondly, random.choice() will make a random choice from the list provided (although it's fairly inefficient to keep reading that from disk every time you call it, and it's unclear why you'd pick one at random, but that's OK), but since you don't actually return the value, the function isn't very useful. A choice is made and then discarded. Instead you probably wanted:
def chosen():
return random.choice(os.listdir(r"/Users/me/p1/images"))
Thirdly, this function definition:
def size():
os.path.getsize(r"/Users/me/p1/images/"+chosen)
It tries to use chosen, but that's just the name of a function you previously defined. You probably want get the size of an actual file that was chosen, which the function needs to be provided with as a parameter:
def size(fn):
return os.path.getsize(r"/Users/me/p1/images/"+fn)
Now to use those functions:
file_size = 0
threshold = 5000
while file_size < threshold:
a_file = chosen()
file_size = size(a_file)
if file_size < threshold:
print(a_file + " is too small")
else:
print(a_file + " is at least 5KB")
print('Done')
The variable file_size is initialised to 0, to make sure the loop starts. The loop will keep going until the condition is met at the start.
Every time, chosen() is executed, the returned value is remembers as the variable a_file, which you can then use in the rest of the code to refer back to.
It then gets passed to size(), to obtain a size and finally, the test is performed to print the right message.
A more efficient way to achieve the same:
threshold = 5000
while True:
a_file = chosen()
file_size = size(a_file)
if file_size < threshold:
print(a_file + " is too small")
else:
break
print(a_file + " is at least 5KB")
The break just exits the while loop which would keep going forever since it tests for True. This avoid testing the same thing twice.
So, you'd end up with:
import random
import os
def chosen():
return random.choice(os.listdir(r"/Users/me/p1/images/"))
def size(fn):
return os.path.getsize(r"/Users/me/p1/images/"+fn)
threshold = 5000
while True:
a_file = chosen()
file_size = size(a_file)
if file_size < threshold:
print(a_file + " is too small")
else:
break
print(a_file + " is at least 5KB")

Why does my code not like this variable? Why is else not working?

Python 3.7 issue.
I'm writing a D&D Character sheet layout with calculators for the inputs. The idea is that if something happens to the character I can update the layout to include it. Such as loss of HP.
So the stats are in a loop and when you get to the end it asks for inputs to update it in the next refresh.
But when I try to write a variable for this particular area it carks it.
And the else statement (also tested on other code) also is hated by the program and when I remove it I get EOF errors.
TL;DR Else statement doesn't work. Variable doesn't work.
Said variable I have changed 3 times and run it on other code with it working fine same with the else.
update = input("Update? ")
if update == "Long Rest":
HP = (8+CM + ((Level-1)*(HitDice+CM)
else:
print (" ")
repeat = input("Continue? ")
if repeat == "Finish":
Finished = True
else:
Finished = False
Finished is a while loop
Whenever I try to run the code I get a pop up box saying "Invalid Syntax". My computer won't let me run the code due to the syntax error.
I'm kind of new to coding but I did look for a similar answer but all the ones I found didn't work.
Everything after the first line should be unindented by one.
The 3rd line doesn't close all the brackets.
Not a syntax issue, but the standard is not to have a space between a function and its arguments.
i.e print (" ") becomes print(" ")
Why do you need to print a space, why not just a new line?
update = input("Update? ")
if update == "Long Rest":
HP = (8 + CM + ((Level - 1) * (HitDice + CM)))
else:
print()
repeat = input("Continue? ")
if repeat == "Finish":
Finished = True
else:
Finished = False

My function is too long. In order to pass class I need < 18 lines

So I am a total beginner yet this is 100% my code and I am proud of it. Now mind you I need a little cleaning up, however it does what I want it too. My issue is this: In order to turn this in for credit, one of the things is that procedures(functions) should not contain more than 18 lines. My function gameCont() has many more. Would anyone have suggestions on how I could shorten it up? Additionally I am obviously challenged when it comes to function parameters so any help is appreciated. Please be gentle as I am BRAND NEW! :)
game1 = "When dealing with SCUBA diving there are many dangers to consider. The very first one is _1_. \
I mean if you take water into your lungs, you are NOT SCUBA diving. Another is rising to the surface too quickly which could \
result in the _2_. Now this is a funny name, as I am sure when it happens, you dont feel 'bendy'. Let's also consider Nitrogen Narcosis.\
If you dont know what that is, well when you are very deep and your body is absorbing more nitrogen than it is used to, you can get \
feeling kinda _3_ feeling as though you just drank not one, but _4_ martinis"
game1_answers = ["drowning", "bends", "drunk", "2"]
game2 = "When you first learn to dive you are taught to do dives within a no DECOmpression limit(NDL). \n This means you do not want to \
stay that deep too long or you will rack up _1_. \n If you DO stay longer than what the NDL allows, you will have an obligation to \
take your time getting to the surface allowing that _2_ gas to leave your body. If you were taking IN gas you may call it \
in-gassing, but when you are decompressing, it may be called _3_-gassing. You are taught also, how to read _4_"
game2_answers = ["deco", "nitrogen", "off", "tables"]
game3 = "Equipment used by cold water divers such as myself are as such. On my head I would wear a _1_. To help regulate the breathing\
pressure from my SCUBA tank I would use a _2_. To help me propel through the water I would place_3_ on my feet. Considering \
we cannot see underwater I need to be wearing a _4_ on my face. Diving in the tropic, many people would use wetsuits, however it's\
very cold where I dive so we wear _5_ suits."
game3_answers = ["hood", "regulator", "fins", "mask", "dry"]
def howManyTries():
gameTries = raw_input("Thanks for giving my quiz a try, how many attempts do you want? ")
return int(gameTries)
def game_choice(): #this function is used to determin which difficulty the user wants and returns the proper game and answer list
user_input = raw_input("Greetings. This is my Udacity project for fill in the blanks. Which one of my options would you like?\
easy, hard, or hardest? Please take note of capitalization ")# this will define the user_input variable to raw input placed in by user
print ("\n" * 20)# just something to clean up the screen
print "Decided to choose " + user_input + '?' " Well " + user_input + " it is"# this confirms to the user which difficulty they chose.
print ""
print ""
if user_input == "easy": #easy returns game1 and game1 answers
return game1, game1_answers
elif user_input == "hard": # hard returns game2 and game2 answers
return game2, game2_answers
elif user_input == "hardest": #hardest returns game3 and game 3 answers
return game3, game3_answers
else:
print "It seems that " + user_input + " is not a valid response" #in case the user doesnt choose or spell choice correctly
def gameCont():
blanks = 1 #this assings blank to 1 which will tell the user which blank they are guessing in below prompt
attempts = howManyTries() #this calls the howManyTries function for a user choice integer
quiz, answers = game_choice() #this returns 2 values (game# and game# answers)
while attempts > 0: #while attempts (called from function) is greater than 0 we will loop this
print quiz #prints the chosen quiz for user updated each time the loop runs with correct answer
print("\n" * 10) #clears some more screen to loook better for the user
guess = raw_input("Reading the above paragraph, What would your guess be for _" + str(blanks) + "_") #asks for guess for current blank which always starts at 1
print("\n" * 10) #clears some more screen to loook better for the user
if guess == answers[blanks - 1]: #because indexing count starts at zero, and blanks start at 1 this will check if answer is equal to blanks - 1
print "As you can see your correct choice has replaced the variable, great job!!"#this will print if the guess is correct
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz
break
elif guess != answers[blanks -1]: #if the answer does not match the list index
attempts = attempts - 1 #then we will subtract 1 from the attempts
print ("\n" * 10)
print "Oops that is not correct, there should be hints in the paragraph" # lets user know they were wrong
print "You have " + str(attempts) + " attempts left." # lets the user know how many attempts they have left
print ""
if attempts < 1:
print "Well it looks like you are out of choices, Try again?"
break
print "Thanks for playing"
gameCont()
All of the printing that you're doing could be done in a separate function
def game_print(newlines_before, text, newlines_after)
print ("\n" * newlines_before + text + "\n" * newlines_after)
Two suggestions:
Delegate tasks that are accomplished by your function to smaller functions. So, for example, if you had a function that needed perform task A and performing that task could be divided into tasks B, C, and D, then create helper functions and call them inside of the function that does task A.
You have long strings, maybe store them somewhere else? Create a class just for constant strings of related functions and access that when you need a particular string. It'll make it less likely that you'll make a mistake when you need to use that string in multiple locations.
class Constants:
str1 = "..."
str2 = "..."
print(Constants.str1)
you can call a function from inside another function. inside an if statement you could call a small new function that just prints some stuff. this should make it easy to get the function size down.
something like this should work:
def correct(quiz, blanks):
print "As you can see your correct choice has replaced the variable, great job!!"
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz`
remember that you still want to break after calling that function in order to exit your loop.

Else statement executing even the IF statement is TRUE

I have a problem in Python language that is described in a title.
for slovo in slova:
if pygame.mouse.get_pressed()[0] and slovo["rect"].collidepoint(pygame.mouse.get_pos()):
for i in range (len(randRijec)):
if slovo["name"] in randRijec[i]:
if i == 0:
slovo1 = randRijec[i].upper()
prvoSlovo = 1
...
...
else:
pogresnoBrojac += 1
slova.remove(slovo)
So, even this IF statement is true, ELSE statement is being executed! However, else statement should be skipped if the if statement is fulfilled.
How to fix this issue?
p.s. I've had this problem few times before and I was not able to solve it...
You have a mixture of tabs and spaces in your code:
Running cat -A test.py (on Unix) yields
for slovo in slova:$
if pygame.mouse.get_pressed()[0] and slovo["rect"].collidepoint(pygame.mouse.get_pos()):$
for i in range (len(randRijec)):$
if slovo["name"] in randRijec[i]:$
if i == 0:$
slovo1 = randRijec[i].upper()$
prvoSlovo = 1$
^I^I^I^I^I^I...$
^I^I^I^I^I^I...$
else:$
pogresnoBrojac += 1$
slova.remove(slovo)$
The ^I indicate tabs.
Thus, the else block is not being interpreted as being at the indentation level on which it appears to be.
Your python code should never mix tabs and spaces for indentation. You can check that your script is not mixing tabs and spaces by running python -t script.py.
In Python you must commit to using either only spaces or only tabs for indentation. PEP8 recommends spaces-only indentation.
You can convert tabs to spaces using the reindent.py program.
So, even this IF statement is true, ELSE statement is being executed!
I can assure you that this is not what happens.
I notice that in the outline of your code the if is inside a for loop. Make sure that in your actual code the else is not accidentally lined up with the for instead of the if. I've seen this mistake more than once.
In Python, for-else is a valid construct. For example, the following is perfectly valid Python:
for i in range(10):
if i < 100:
pass
else:
print 'In else clause'
When run, this prints out In else clause.
Contrast this with the following, which doesn't print anything when run:
for i in range(10):
if i < 100:
pass
else:
print 'In else clause'
It's a question from a long time ago and I stumbled upon it as I was troubleshooting the very same issue - the solution was actually pretty silly and most probably was also the case - as it's a for loop it iterates through every list element, if even one of those elements doesn't fulfill the if condition, it will automatically trigger the else - pretty self-evident but easy to miss for beginners.
Well at least that was the problem in my case :)
Next solution fixed my problem:
for slovo in slova:
if pygame.mouse.get_pressed()[0] and slovo["rect"].collidepoint(pygame.mouse.get_pos()):
xy = 0
for i in range (len(randRijec)):
if slovo["name"] in randRijec[i]:
xy = 1
if i == 0:
slovo1 = randRijec[i].upper()
prvoSlovo = 1
break
if i == 1:
slovo2 = randRijec[i].upper()
drugoSlovo = 1
break
slova.remove(slovo)
if xy == 0:
pogresnoBrojac += 1
...
...
...
xy = 1
pygame.display.update()
time.tick(value)
So, I have just added that xy counter that makes my code work how it should work. When IF statement is met, xy becomes 1, if IF statement isn't fulfilled, xy is set to 0 and then this "else" statement executes. At the end of the code, xy is set to 1 again to prevent executing this "else" (if xy == 0) block.

Can't get my loop & match to append to correct list

I´m experiencing problems with my code.
I can´t get it to append to the list not_found as well as it loops twice for some reason.
Can anyone point me in the right direction? The match works for my_track, but it doesn't when it doesn't match.
# coding: utf-8
#!/usr/bin/env python
import spotimeta
import sys
import time
my_tracks = raw_input("Please enter a sentence: ").title().split()
playlist = []
real_playlist = []
not_found = []
def check_track(track_name, my_track, track_href):
if track_name == my_track:
playlist.append(track_href)
return 1
# make sure the user does not input a single word as input
if (len(my_tracks) > 1):
path = my_tracks[1]
else:
sys.exit("Invalid input, please enter a sentence.")
# let's search
for my_track in my_tracks:
match = 0
print "Searching for '%s'\n" % (my_track),
data = spotimeta.search_track(my_track)
for result in data['result']:
if not match == 1:
try:
match = check_track(result["name"],my_track,result["href"])
except Exception, e:
error = "not available"
else:
if data['total_results'] > 0:
not_found.append(my_track)
You should try debugging it. One of the simplest ways of debugging is add the lines:
import pdb
pdb.set_trace()
Then when you run the script it will stop at the set_trace line in the debugger.
Check out http://docs.python.org/library/pdb.html for more information.
From my understanding you're trying to do something like:
for my_track in my_tracks:
print "Searching for '%s'\n" % (my_track),
data = spotimeta.search_track(my_track)
for result in data['result']:
if result['name'] == my_track:
playlist.append(result['href'])
elif data['total_results'] > 0:
not_found.append(my_track)
Will this more or less work for you?
Please help me to understand.
Right off the bat, I'm noticing two things.
First, you're checking data['total_results'] a bit late; if the total results value is greater than zero (wait, what?), then you want to add it to the list immediately and move on without parsing the data. I would, after the call from spotimeta.search_track(), check to see if this is the data you don't want (then subsequently add it into the list).
Second, I'm confused about the intention of your for loop. If you're going through it to only find one item, then you can use the in statement (my_track in result).

Categories

Resources