1

I use Path.iterdir() to go through a list of directories and do so some work.

from pathlib import Path

for folder in repository.iterdir():
    # do some work

After completing that task, if it's successful the directories should be empty. I'm aware that you shouldn't modify a list you're iterating over, so doing this I assume would be bad practice, correct?

for folder in repository.iterdir():
    folder.rmdir()

Instead what I did was collect a list of directories that are empty and then use that list to remove the directories, like this:

# Get a list of all the directories that are empty.
directories_to_remove = [folder for folder in repository.iterdir() if not os.listdir(folder)]

# Remove all the directories that are empty
for folder in directories_to_remove:
    folder.rmdir()

The folder paths still exists in directories_to_remove so I'm not modifying a list I'm iterating over, is this the correct way to delete the directories from the drive?

киска
  • 137
  • 1
  • 7

3 Answers3

0

That is a correct way to remove the actual directory, but you are correct in that you are not removing it from directories_to_remove

If you'd like to, you could simply change:

for folder in directories_to_remove:
    folder.rmdir()

to

for folder in directories_to_remove:
    folder.rmdir()
    directories_to_remove.remove(folder)

But, if your intentions are to not remove it from the list while iterating, you are succeeding, good job :)

artemis
  • 6,857
  • 11
  • 46
  • 99
  • The second piece of code is exactly what one _should't_ do. Check what this code outputs: `a = [1,2,3]; for x in a: a.remove(x); print(a)`. Note how it doesn't output an empty list after the loop. – ForceBru Jul 18 '19 at 13:45
  • Correct, and I don't think I implied you should do that (if I did, I need to check my English :)), but I was unsure if the OP had an intention to do that. – artemis Jul 18 '19 at 13:46
  • The point is, removing items from a list while iterating over it [_doesn't work_](https://stackoverflow.com/a/1207427/4354477) – ForceBru Jul 18 '19 at 13:49
  • @JerryM. - I don't want to remove the directories from the `directories_to_remove` list while iterating over it. I can do it all at once afterward, correct? With `directories_to_remove.clear()`? – киска Jul 18 '19 at 14:15
  • Absolutely correct! You should not remove things while iterating. Once you are done, you can use `.clear()` to completely remove everything from the list. See the reference here: https://www.programiz.com/python-programming/methods/list/clear – artemis Jul 18 '19 at 14:17
0

iterdir doesn't remove a list, so you're good. Moreover, if it did return a list, your code doesn't delete any items from it, so it would've been fine anyway, as long as the directories are actually deleted, of course.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
0

What happens when iterating over data in Python is determined by the iterator and problems are likely to occure when altering the iterable this iterator refers to. If you do iterate over a list that was created once, you can maipulate the data it was created from without any harm. But since iterdir "yields" values, it appears to be a generator thus it fetches the data on the fly, and whether or not bad things happen depends on its implementation (and/ or the implementation of the underlying system calls).

Unless you have severe performance or memory troubles I would not take the chance and fetch all data before processing it:

for folder in [repository.iterdir()]:
    folder.rmdir()

Note thought that this is not 100% safe either since there might be a case where the directories are filled, altered or removed before you hit the folder.rmdir() but this is highly unlikely unless you use multiprossessing.

hajef
  • 334
  • 2
  • 13