OVH Cloud OVH Cloud

walk

14 réponses
Avatar
Do Re Mi chel La Si Do
Bonjour !

os.walk est dans la librairie standard. Je pensait que c'était une garantie
d'optimisation.
Or, en comparant ces deux fonctions :


def ess1(srep,topdown=False):
lsou=[]
for root, dirs, files in os.walk(srep):
lsou.append(root)
return lsou

def ess2(srep,lsou=[]):
for i in os.listdir(srep):
ste=srep+'\\'+i
if os.path.isdir(ste):
lsou.append(ste)
lsou=ess2(ste,lsou)
return lsou

#ess1(r'D:\Dev\Python')
#ess2(r'D:\Dev\Python')


il s'avère que ess2 est plus rapide que ess1. Pourquoi ?



@-pluche

Michel Claveau

10 réponses

1 2
Avatar
Laurent Coustet
Do Re Mi chel La Si Do wrote:
il s'avère que ess2 est plus rapide que ess1. Pourquoi ?


RTSL :)

--
Laurent

Avatar
Do Re Mi chel La Si Do
Bonjour !

RTSL = Réellement Tordant & Semi-Lol ?

Te moquerais-tu ?



Michel Claveau
Avatar
Amaury
#ess1(r'D:DevPython')
#ess2(r'D:DevPython')

il s'avère que ess2 est plus rapide que ess1. Pourquoi ?


En faisant le test, j'ai cru que tu avais raison.
Mais en fait, ess1 est plus lent parce qu'il est exécuté avant ! C'est
le temps d'accès au disque dur.
Lors de l'exécution de ess2, le contenu des répertoires est en mémoire
cache.

En relançant les deux commandes plusieurs fois, elles mettent presque le
même temps.

Amaury.

Avatar
Amaury
Bonjour !

RTSL = Réellement Tordant & Semi-Lol ?


En fait, j'ai appris récemment que ça veut dire
"Read The Source, Luke"
qui est une déformation de Maître Yoda:
"Use The Force, Luke" (je traduis pas)


Te moquerais-tu ?



Pas tout à fait. En lisant bien, on voit que la première fonction
construit la liste des fichiers de chaque répertoire, alors que la
deuxième ne construit que la liste des noms de répertoire. Mais ce n'est
pas ça qui prend le plus de temps...

Amaury

Avatar
Do Re Mi chel La Si Do
'soir !

J'ai fait les tests dans les deux sens, avec de "gros" sous-répertoires .
Et j'ai toujours un écart, pas très important, c'est vrai, mais
systématiquement en faveur de ess2

Le fait que je suis sous XP-NTFS peut, peut-être, jouer aussi.

Ce n'est pas très important. Mais, je suis simplement déçu par ce
comportement de la librairie standard.

--
Michel Claveau
Avatar
Christophe Cavalaria
Do Re Mi chel La Si Do wrote:

Bonjour !

os.walk est dans la librairie standard. Je pensait que c'était une
garantie d'optimisation.
Or, en comparant ces deux fonctions :


def ess1(srep,topdownúlse):
lsou=[]
for root, dirs, files in os.walk(srep):
lsou.append(root)
return lsou

def ess2(srep,lsou=[]):
for i in os.listdir(srep):
ste=srep+''+i
if os.path.isdir(ste):
lsou.append(ste)
lsou=ess2(ste,lsou)
return lsou

#ess1(r'D:DevPython')
#ess2(r'D:DevPython')


il s'avère que ess2 est plus rapide que ess1. Pourquoi ?



@-pluche

Michel Claveau


Un coup d'oeil au source permet de répondre à cette question mais je vais
d'abord commencer par une question moi même :
- A quoi sert-il de définir le paramètre topdown de ess1 avec une valeur par
defaut a False ?

Ensuite, le code source nous montre plusieures choses en plus que fait
os.walk que ne sait pas faire ess2 :
- utilisation de os.path.join pour concatener les noms de fichier. Le
résultat est portable comme ça au moins et sans aucun doute moins rapide
que la concatenation brute par chaine ste=srep+''+i
- verification de la présence de liens symboliques encore une fois pour des
raisons de portabilité. Cela cause donc un appel de fonction de plus par
fichier, appel indispensable pour les systèmes supportant les liens
symboliques

Avatar
Do Re Mi chel La Si Do
Bonjour

En essayant, j'ai trouvé une méthode nettement plus rapide :

def lsousrep2(srep):
pipe = subprocess.Popen('dir '+srep+' /s /w', shell=True,
stdout=subprocess.PIPE).stdout
compilre=re.compile(r' Répertoire de ')
result=[]
for lig in pipe.readlines():
if compilre.search(lig):
result.append(lig)
return result


Simplement en wrappant Windows !

A vous dégoûter de programmer...


@-salutations

Michel Claveau
Avatar
Do Re Mi chel La Si Do
Bonjour !


A quoi sert-il de définir le paramètre topdown de ess1 avec une valeur
par defaut a False ?




Cela paramètre os.walk, pour qu'il mémorise les noms des répertoires, après
avoir parcouru les sous-répertoires. Avec topdown=True, la mémorisation se
ferait avant.


Pour le reste, je me doute que os.walk fait plus de choses (explication
logique). Je ne suis pas sûr que les liens symboliques, inexistants sous
windows, jouent beaucoup ; par contre il doit y avoir de nombreux tests pour
portabilité (OS, version, etc.) qui doivent peser.


Conclusion : principes et croyances ne devraient être que des hypothèses.


@-salutations

Michel Claveau



Avatar
Amaury
Bonjour,

J'ai fait quelques tests (vive le module hotshot), et il s'avère que
c'est os.path.join qui est la cause de la "lenteur" de os.walk.

En remplaçant tous les join par des " +os.path.sep+ ", les deux
fonctions vont à la même vitesse.

Et c'est vrai qu'il y a une piste d'optimisation possible pour os.walk :
on peut se passer de la généralité de os.path.join car on sait déjà que
le premier élément n'est pas vide, et que le second n'est pas un chemin
absolu.

Amaury.
Avatar
Do Re Mi chel La Si Do
Re

C'est toujours bon à savoir.
Et, comme l'autre méthode est aussi rapide, ça laisse le choix.

@-salutations

Michel Claveau
1 2