Home > Net >  Running the same program until condition satisfied
Running the same program until condition satisfied

Time:11-26

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.

CodePudding user response:

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")
  • Related