11
votes

Équivalent python de la sortie du fichier de tuyauterie à GZIP en Perl à l'aide d'un tuyau

Je dois déterminer comment écrire la sortie de fichier dans un fichier compressé en Python, similaire à la doublure ci-dessous: xxx pré>

en Perl, cela utilise UNIX GZIP pour compresser ce que vous Imprimez sur le fichier de fichiers zippé dans le fichier "zipped.gz". P>

Je sais utiliser "Importer gzip" pour le faire dans Python comme ceci: P>

import gzip
zipped = gzip.open("zipped.gz", 'wb')
zipped.write("Hello world\n")


4 commentaires

En avez-vous besoin de cela dans Pure Python ou pourriez-vous vous contenter d'un appel dans un binaire sur votre système de fichiers (en python, vous utiliseriez le module de sous-trafiscess)?


Je préfère ne pas le faire en python puisque les méthodes python python sont trop lentes.


Avez-vous exécuté le programme GZIP de la coquille sur votre 200 Go de données non compressées? Je m'attendrais à ce que cela prenne un peu de temps de Wallclock à 90-100% d'utilisation du processeur - sur ma boîte à vitres, il fonctionne environ 1 minute par Go, alors que le module Gzip Python prend environ 2 minutes par Go.


Dave, oui c'est la différence entre les 2 minutes et 1 minute que je vais après.


5 Réponses :


2
votes

Utilisation de Module GZIP est Le fonctionnaire à sens unique et à faire et il est peu probable que toute autre approche python python soit plus rapide. Ceci est particulièrement vrai car la taille de vos données exclut les options de mémoire. Très probablement, le moyen le plus rapide est d'écrire le fichier complet sur le disque et d'utiliser Subprocess à appeler gz sur ce fichier.


0 commentaires

10
votes

suggestion de Christophed d'utiliser le Le module de sous-processus est une réponse appropriée à cette question. Cependant, ce n'est pas clair pour moi qu'il résoudra vos problèmes de performance. Vous devriez mesurer les performances du nouveau code pour être sûr.

Pour convertir votre code d'échantillon: P>

import subprocess

p = subprocess.Popen("gzip -c > zipped.gz", shell=True, stdin=subprocess.PIPE)
p.stdin.write("Some data")

# Write more data here...

p.communicate() # Finish writing data and wait for subprocess to finish


4 commentaires

J'ai vérifié que cette méthode est de 33% plus rapide sur un fichier hautement compressible de 1 Go. C'est une bonne amélioration par rapport à gzip.open. Voici le code que j'ai utilisé pour le tester: Importer Subprocess Text = "FJLASKFJIOWRU OIJF ALKSFJLKQS JR JWEQOIRJWOIEFJLKADSFJ AFJF \ N" POUR I IN XRANGE (1,25): Texte + = Texte P = Subprocess.Popen ("gzip -c> zippé. gz ", shell = true, stdin = sous-processus.pipe)` p.stdin.write (texte) p.com Municate () Temps pour gzip.open: 12.109u 1.194s 0: 13.37 99.4% 0 + 0k 0 + 0PF + 0PF + 0w Time pour le code ci-dessus: 8.379U 2.602S 0: 10.17 107.8% 0 + 0k 0 + 0IO 0PF + 0W


Assurez-vous d'accepter votre réponse préférée :-). Nous aimons tous le représentant supplémentaire.


Pour le curieux, le temps d'exécution d'un gros test est tombé de 6h43m à 4h31m lorsque j'ai utilisé cette méthode par opposition à gzip.open. C'était des pommes-à-pommes sur la même machine. Ceci est environ 33% plus rapide, ce qui est exactement ce que j'ai vu dans le plus petit cas de test. Merci tout le monde!


@ bu11d0zer: vous devriez utiliser Pastebin pour ce genre de chose: Pastebin.com/2kzhsbfh



6
votes

Essayez quelque chose comme ceci:

from subprocess import Popen, PIPE
f = open('zipped.gz', 'w')
pipe = Popen('gzip', stdin=PIPE, stdout=f)
pipe.communicate('Hello world\n')
f.close()


0 commentaires

0
votes

En plus de @srgerg S Réponse Je veux appliquer la même approche en désactivant l'option Shell shell = false , qui est également effectuée sur la réponse de @moiche Lettvin et recommandé sur ( https://stackoverflow.com/a/3172488/2402577 ). XXX


S'il vous plaît pas à l'origine que j'utilise à l'origine que j'utilise cette sortie P1 S pour git diff comme:

p1 = subprocess.popen (["git", "diff"], stdout = sous-processus.pipe)


0 commentaires

1
votes

Assurez-vous d'utiliser le même niveau de compression lors de la comparaison des vitesses. Par défaut, Linux GZIP utilise le niveau 6, tandis que Python utilise le niveau 9. J'ai testé cela dans Python 3.6.8 à l'aide de GZIP version 1.5, compressant 600 Mo de données de MySQL Dump. Avec Paramètres par défaut:

Module Python prend 9,24 secondes et fait un fichier 47.1 MB de
Subprocess GZIP prend 8,61 secondes et fait un fichier 48,5 mb

après le modifié au niveau 6 afin qu'ils correspondent à:
Le module Python prend 8,09 secondes et fait un fichier de 48,6 Mo de
Subprocess GZIP prend 8,55 secondes et fait un fichier 48,5 mb xxx


0 commentaires