web-dev-qa-db-fra.com

Dans quel ordre os.walk itère-t-il itère?

Je suis préoccupé par l'ordre des fichiers et des répertoires donné par os.walk(). Si j'ai ces répertoires, 1, 10, 11, 12, 2, 20, 21, 22, 3, 30, 31, 32, quel est l'ordre de la liste de sortie?

Est-il trié par valeurs numériques?

1 2 3 10 20 30 11 21 31 12 22 32

Ou trié par ASCII valeurs, comme ce qui est donné par ls?

1 10 11 12 2 20 21 22 3 30 31 32

De plus, comment puis-je obtenir un tri spécifique?

57
Vahid Mirjalili

os.walk Utilise os.listdir. Voici la docstring pour os.listdir:

listdir (chemin) -> list_of_strings

Renvoie une liste contenant les noms des entrées du répertoire.

path: path of directory to list

La liste est dans un ordre arbitraire . Il n'inclut pas les entrées spéciales "." et '..' même s'ils sont présents dans le répertoire.

(c'est moi qui souligne).

Vous pouvez cependant utiliser sort pour assurer l'ordre que vous désirez.

for root, dirs, files in os.walk(path):
   for dirname in sorted(dirs):
        print(dirname)

(Notez que les dirnames sont des chaînes et non des entiers, donc sorted(dirs) les trie en chaînes - ce qui est souhaitable pour une fois.

Comme le soulignent Alfe et Ciro Santilli, si vous voulez que les répertoires soient récursifs dans un ordre trié, modifiez dirs en place:

for root, dirs, files in os.walk(path):
   dirs.sort()
   for dirname in dirs:
        print(os.path.join(root, dirname))

Vous pouvez le tester vous-même:

import os

os.chdir('/tmp/tmp')
for dirname in '1 10 11 12 2 20 21 22 3 30 31 32'.split():
     try:
          os.makedirs(dirname)
     except OSError: pass


for root, dirs, files in os.walk('.'):
   for dirname in sorted(dirs):
        print(dirname)

impressions

1
10
11
12
2
20
21
22
3
30
31
32

Si vous souhaitez les répertorier par ordre numérique, utilisez:

for dirname in sorted(dirs, key=int):

Pour trier les chaînes alphanumériques, utilisez tri naturel .

84
unutbu

os.walk() donne à chaque étape ce qu'elle fera dans les étapes suivantes. Vous pouvez à chaque étape influencer l'ordre des étapes suivantes en triant les listes comme vous le souhaitez. Citant le manuel 2.7 :

Lorsque topdown a la valeur True, l'appelant peut modifier la liste des noms de répertoire sur place (peut-être en utilisant l'affectation del ou slice), et walk () ne récursera que dans les sous-répertoires dont les noms restent dans les noms de répertoire; cela peut être utilisé pour élaguer la recherche, imposer un ordre de visite spécifique

Le tri des dirNames influencera donc l'ordre dans lequel ils seront visités:

for rootName, dirNames, fileNames in os.walk(path):
  dirNames.sort()  # you may want to use the args cmp, key and reverse here

Après cela, les dirNames sont triés sur place et les prochaines valeurs produites de walk seront en conséquence.

Bien sûr, vous pouvez également trier la liste de fileNames mais cela n'influencera pas les étapes suivantes (car les fichiers n'ont pas de descendants walk sera visité).

Et bien sûr, vous pouvez parcourir les versions triées de ces listes comme le propose la réponse d'unutbu, mais cela n'influencera pas la progression future du walk lui-même.

L'ordre non modifié des valeurs n'est pas défini par os.walk, ce qui signifie que ce sera "n'importe quelle" commande. Vous ne devez pas vous fier à ce que vous vivez aujourd'hui. Mais en fait, ce sera probablement ce que le système de fichiers sous-jacent renvoie. Dans certains systèmes de fichiers, cela sera classé par ordre alphabétique.

34
Alfe

Le moyen le plus simple consiste à trier les valeurs de retour de os.walk(), par ex. en utilisant:

for rootName, dirNames, fileNames in sorted(os.walk(path)):
    #root, dirs and files are iterated in order... 
25
vpuente