Dans un script python, j'utilise la fonction difflib.unified_diff() pour recevoir les différences de deux fichiers. Ensuite, en suivant cet exemple, J'appelle la fonction writelines () pour écrire le résultat à l'écran:

diff = difflib.unified_diff( .... )
sys.stdout.writelines(diff)

Ensuite, je souhaite également écrire les différences dans un fichier, mais je reçois un fichier vide. Voici la partie étrange: si j'échange l'ordre des deux appels de writelines (), j'obtiens un fichier correct mais une sortie d'écran vide. Le même problème peut également être reproduit en appelant simplement la dernière commande deux fois, comme ceci:

diff = difflib.unified_diff( .... )
sys.stdout.writelines(diff)
sys.stdout.writelines(diff)

Cela n'imprimera le diff qu'une seule fois.

Je suppose que la deuxième fois, la fonction continue à partir de la même (c'est-à-dire la dernière) "ligne" de diff et n'a rien à écrire. Donc, il doit y avoir une sorte d'itérateur que je dois réinitialiser, mais je n'ai pas pu trouver quoi et comment ...

1
MakisH 10 juil. 2015 à 15:25

2 réponses

Meilleure réponse

difflib.unified_diff() renvoie un générateur . Il ne produit la sortie que une fois lors de l'itération.

Si vous devez l'écrire deux fois, capturez d'abord les lignes dans une liste:

diff = list(difflib.unified_diff( .... ))
sys.stdout.writelines(diff)
sys.stdout.writelines(diff)

À partir de la difflib.unified_diff() documentation:

Comparez a et b (listes de chaînes); renvoie un delta ( un générateur générer les lignes delta ) au format diff unifié.

Mine d'accentuation en gras .

1
Martijn Pieters 10 juil. 2015 à 12:26

Vous avez consommé le générateur après la première écriture renvoyée par unified_diff.

difflib.unified_diff (a, b [, fromfile] [, tofile] [, fromfiledate] [, tofiledate] [, n] [, lineterm])

Comparez a et b (listes de chaînes); renvoie un delta (un générateur générant les lignes delta) au format diff unifié.

Vous devez stocker la sortie dans une liste si vous souhaitez l'utiliser deux fois.

diff = list(difflib.unified_diff( .... ))

Une fois que vous effectuez une itération sur un générateur une fois, il a été consommé, il n'y a donc rien à itérer la deuxième fois:

In [13]: gen = (i for i in (1,2,3))    
In [14]: for i in gen:
           print(i)
   ....:     
1
2
3   
In [15]: for i in gen: # already been consumed
           print(i)
   ....:     

Appeler la liste sur la génération signifie que vous stockez toutes les lignes dans une liste afin que vous puissiez itérer et utiliser les lignes autant de fois que nécessaire:

In [19]: gen = (i for i in (1,2,3))    
In [20]: l = list(gen)    
In [21]: for i in l:
           print(i)
   ....:     
1
2
3    
In [22]: for i in l:
             print(i)
   ....:     
1
2
3
1
Padraic Cunningham 10 juil. 2015 à 12:35