2

I'm trying to use a while loop to loop through .xml files in a folder. However, files are being added to the folder whilst the while loop is running. This is a shortened version of the code I currently use:

import os

my_folder = "d:\\xml\\"

while True:
    files = [f for f in os.listdir(my_folder) if f.endswith(".xml")]
    while files:
        for file in files:
            # do whatever with the xml file
            os.remove(my_folder + file)
        files = [f for f in os.listdir(my_folder) if f.endswith(".xml")]

What I would like to do is tidy up the code by only having one line filling the files list. I'd like to have something like:

while files = [f for f in os.listdir(my_folder) if f.endswith(".xml")]:

But, I know this won't work. I would imagine that Python is capable of this, but I don't know the correct syntax.

Added note: I'm using Windows 10 with Python 3.7.6

7
  • Possibly related: stackoverflow.com/q/4708511/1639625 Commented Nov 11, 2020 at 14:38
  • 1
    Can't you remove the inner while and use just while True: files = ...; for file in files: ... ? Commented Nov 11, 2020 at 14:39
  • Since 3.8 there is the assignment operator while files := [f for f... Commented Nov 11, 2020 at 14:42
  • I like the two loops approach better. You could use a function to make the division of jobs more clear, but the general idea is the outer loop gets a one-time snapshot, processes it, and then does time.sleep. The inner loop works on that snapshot until done. Commented Nov 11, 2020 at 14:43
  • I suppose it would as it would just ignore the "for file in files" loop if there were no files... Commented Nov 11, 2020 at 14:44

1 Answer 1

1

You could simplify your code by removing the inner while loop and the second assignment to files. This will loop indefinitely, see if there are xml files in the directory, and if so process and delete them, before continuing to loop. (You might also add a short sleep in case of no new files.)

while True:
    files = [f for f in os.listdir(my_folder) if f.endswith(".xml")]
    for file in files:
        # do whatever with the xml file
        os.remove(my_folder + file)
    

As shown in the other answer, you could also use the := operator and something like the following...

while True:
    while (files := [...]):
        ...

... but this would behave exactly the same as without the inner while. Only if you e.g. want to do something when there are temporarily no files left, i.e. have code in the outer loop that's not in the inner loop, this may make a difference.

Sign up to request clarification or add additional context in comments.

2 Comments

I suppose you could do while (files := [...]) or True:. But the first solution still seems better - especially if for path in glob(...): is used instead.
@ekhumoro That while with := would just save one line; you'd still need the for, and you could do the same with moving the list comprehension directly to the for loop head. But using for file in glob.glob("*.xml") is indeed a nice idea that makes it more readable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.