Python Pipes – Que se passe-t-il lors de la lecture incrémentielle

Selon une section de ce livre présumé précis ,

Une utilisation courante des pipes est de lire un fichier compressé de manière incrémentielle; c’est-à-dire sans décompresser le tout en même temps. La fonction suivante prend le nom d’un fichier compressé en tant que paramètre et retourne un canal qui utilise gunzip pour décompresser le contenu:

def open_gunzip(filename): cmd = 'gunzip -c ' + filename fp = os.popen(cmd) return fp 

Si vous lisez les lignes de fp une à la fois, vous ne devez jamais stocker le fichier non compressé en mémoire ou sur disque.

Peut-être que je ne fais qu’interpréter cette erreur, mais je ne vois pas comment cela est possible. Python ne pouvait avoir aucun moyen d’arrêter Gunzip à mi-chemin en crachant les résultats, non? Je suppose que gunzip ne va pas bloquer jusqu’à ce qu’une ligne de sortie soit lue avant de continuer à produire plus de lignes, donc un tampon doit capturer tout cela (que ce soit dans l’interpréteur Python ou dans le système d’exploitation, en mémoire ou sur disque) ), ce qui signifie que le fichier non compressé est stocké quelque part en entier … non?

Votre hypothèse est défectueuse. gunzip n’a pas besoin de voir le fichier entier pour le décompresser. Lisez le format de fichier de décompression. Il y a un répertoire, avec des décalages pour les composants individuels.

Il est possible de décompresser un fichier en morceaux.

“le fichier non compressé est stocké quelque part en entier … non?”

Pas nécessairement. Vous ne savez pas pourquoi vous le prenez ou où vous le lisez.

Tous les appels d’E / S de bas niveau peuvent bloquer. Le script write in gunzip – lors de l’écriture sur un tube – peut bloquer lorsque le buffer de tube est plein. C’est comme ça que les E / S sur un tube sont définies. Blocs de tuyaux I / O.

Consultez les pages de manuel relatives à pipe pour plus de détails.

Si un processus tente de lire à partir d’un tuyau vide, alors read (2)
bloquer jusqu’à ce que les données soient disponibles. Si un processus tente d’écrire sur un
tube complet (voir ci-dessous), puis écrire (2) blocs jusqu’à ce que suffisamment de données
été lu depuis le tube pour permettre à l’écriture de se terminer. Non bloquant
I / O est possible en utilisant l’opération fcntl (2) F_SETFL pour activer le
O_NONBLOCK Indicateur d’état du fichier ouvert.

Cela vient vraiment de l’implémentation de gunzip , pas de python. Il est écrit en C. Il utilise probablement fwrite() du stdio.h de C pour écrire sa sortie.

libc6 implémentation de libc6 que j’utilise crée automatiquement un tampon de sortie, et quand il est rempli, il bloque fwrite() jusqu’à ce qu’il puisse écrire plus.

Ce n’est pas Python qui suspend gunzip , c’est que le kernel arrête d’exécuter gunzip quand il essaie d’écrire (en utilisant le syscall write() ) dans un tampon complet. Cela s’appelle le blocage sur IO . Le kernel maintient un tampon interne reliant les deux extrémités de la ligne de pliage, indépendamment de toute mise en mémoire tampon se produisant dans les processus qui écrivent ou lisent à partir du canal.

Python bloquera de la même manière lors de la lecture d’un tube contenant un tampon vide, c’est-à-dire qui ne contient aucune donnée écrite par gunzip .

Les tuyaux peuvent être considérés comme une solution au problème producteur-consommateur .