2016-08-14 4 views
1

Je rencontre une erreur qui peut probablement être contournée mais qui me perturbe le concept et je me demande si quelqu'un pourrait éclaircir quelque chose.Utilisation de shutil.rmtree() dans une fonction récursive (Windows 10)

Lorsque je répète via la structure de répertoire appelant shutil.rmtree() sous certaines conditions, j'obtiens une erreur qui équivaut à une tentative de suppression d'un objet déjà supprimé. Voici un exemple simple:

def deleteFolder(path): 
    for obj in glob.glob(os.path.join(path, '*')): 
     print('obj name is ',obj) 
     if os.path.isdir(obj): 
      deleteFolder(obj) 
    print('removing path ',path) 
    print(os.listdir(path)) 
    shutil.rmtree(path,False) 


WindowsError        Traceback (most recent call last) 
<ipython-input-36-ad9561d5fc92> in <module>() 
     2 #path = 'C:\Users\Wes\Desktop\Test\Morphine\Album1' 
     3 #shutil.rmtree(path) 
----> 4 deleteFolder('C:\Users\Wes\Desktop\Test\Level1') 

<ipython-input-35-14a315bc6a80> in deleteFolder(path) 
    30  print('removing path ',path) 
    31  print(os.listdir(path)) 
---> 32  shutil.rmtree(path,False) 

C:\Users\Wes\Anaconda2\lib\shutil.pyc in rmtree(path, ignore_errors, onerror) 
    250     os.remove(fullname) 
    251    except os.error, err: 
--> 252     onerror(os.remove, fullname, sys.exc_info()) 
    253  try: 
    254   os.rmdir(path) 

C:\Users\Wes\Anaconda2\lib\shutil.pyc in rmtree(path, ignore_errors, onerror) 
    248   else: 
    249    try: 
--> 250     os.remove(fullname) 
    251    except os.error, err: 
    252     onerror(os.remove, fullname, sys.exc_info()) 

WindowsError: [Error 2] The system cannot find the file specified: 'C:\\Users\\Wes\\Desktop\\Test\\Level1\\Level2' 
Structure

répertoire est/Niveau1/Level2/Level3 et fx est appelé w/arg niveau1. Évidemment, c'est un exemple stupide, il fait la récursivité pour laquelle shutil.rmtree est construit, mais quand vous ajoutez une condition à la suppression ou non du répertoire, cela a plus de sens.

Voici la sortie d'impression:

('obj name is ', 'C:\\Users\\Wes\\Desktop\\Test\\Level1\\Level2') 
('obj name is ', 'C:\\Users\\Wes\\Desktop\\Test\\Level1\\Level2\\Level3') 
('removing path ', 'C:\\Users\\Wes\\Desktop\\Test\\Level1\\Level2\\Level3') 
[] 
('removing path ', 'C:\\Users\\Wes\\Desktop\\Test\\Level1\\Level2') 
[] 
('removing path ', 'C:\\Users\\Wes\\Desktop\\Test\\Level1') 
['Level2'] 

Il semble descendre à Level3, supprimer Level3, se déplace jusqu'à Level2, n'a pas de problème vu que Level3 n'est plus subdir de Level2, supprime Level2 , mais Level1 voit toujours Level2 et les erreurs. Il semble y avoir une certaine subtilité de la portée en ce qui concerne os.path que je suis manquant. En fin de compte, j'aimerais explorer un arbre entier en commençant par des répertoires racine et élagage qui n'ont pas de descendants répondant à certains critères (contenant des fichiers audio).

+0

pourriez-vous mettre la sortie complète avec traceback ensemble tous ensemble, je ne suis pas entièrement sûr de ce qui ne va pas. –

+0

Edité ci-dessus pour inclure trace complète – Wes

+0

hmm ... est-ce reproductible? (si vous mettez les dossiers comment ils étaient et courez encore vous obtenez la même erreur?) 'shutil.rmtree' utilise' os.listdir' pour trouver le contenu à supprimer de sorte que le 'os.listdir' signale incorrectement que' Level2' est toujours présent est certainement la cause du problème. –

Répondre

0

Je pense, votre problème peut être lié à celui-ci: Permission denied doing os.mkdir(d) after running shutil.rmtree(d) in Python

shutil.rmtree sur Windows arrive à revenir pas lorsque les fichiers sont effectivement supprimés. Vous pouvez imaginer que cela est fait de manière asynchrone de sorte que rmtree appelle may conflict. Aussi, c'est pourquoi pip install échoue parfois lors de la suppression de ses fichiers mis en cache en utilisant shutil.rmtree pendant la phase de nettoyage. Essayez de mettre time.sleep(1) après chaque appel rmtree - cela aide-t-il? Si c'est le cas, votre solution serait soit de réessayer de supprimer des fichiers après une telle erreur ou de collecter les répertoires à supprimer et de les supprimer sélectivement pour éviter les conflits.

+0

Suppression de fichiers et de répertoires sous Windows utilise une poignée ouverte pour définir la disposition de suppression sur le bloc de contrôle du système de fichiers sous-jacent. Il peut exister d'autres références de pointeur de noyau et de poignée (par exemple, un scanner de logiciels malveillants). Toutes ces références sont suivies et le fichier est supprimé et dissocié uniquement lorsque le nombre de références tombe à zéro. À ce stade, il est possible qu'un autre appel ait déjà commencé à répertorier le répertoire parent, qui voit un fichier ou un répertoire devant être supprimé. – eryksun

+0

Une boucle après l'appel récursif 'de deleteFolder' peut vérifier' 'os.listdir' jusqu'à ce que obj' est dissociées. Peut-être vérifier jusqu'à la seconde avant de lever une exception. – eryksun

+0

Cela semble être la réponse. Merci eryksun je vais essayer votre solution pour éviter le temps d'attente fixe. – Wes