2011-11-28 4 views
9

bir boru kullanarak Perl gzip Bu, ZIPPED dosya kümesine ne yazdıracağınızı sıkıştırmak için Unix gzip dosyasını "zipped.gz" dosyasına kullanır. Python eşdeğer aşağıda iki astar benzer Python sıkıştırılmış bir dosyada, dosya çıktı yazmak için nasıl anlamaya ihtiyacımız

böyle Python Bunu yapmak için "ithal gzip" kullanmayı biliyor:

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

Ancak, bu son derece yavaştır. Profiler göre, bu yöntem kullanarak çeşitli çıkış dosyalarına 200 GB sıkıştırılmamış veri yazıyorum çünkü benim çalışma süresinin% 90 kadar alır. Dosya sisteminin buradaki problemin bir parçası olabileceğinin farkındayım, ancak bunun yerine Unix/Linux sıkıştırması kullanarak bunu yönetmek istiyorum. Bu kısmen, aynı modülü kullanarak açma işlemini yavaşlattığını duyduğumdan dolayı. gzip module kullanma

+1

bunu saf Python yapılması mi istiyorsunuz, yoksa dosya sistemi üzerinde bir ikili bir çağrıda razı olabilir (Python, altişlem modülü kullanmak istiyorum)? – ChristopheD

+0

Saf Python yöntemleri çok yavaş olduğu için Python'da yapmamayı tercih ederim. – bu11d0zer

+0

gzip programını 200 GB sıkıştırılmamış verilerinizdeki kabuktan mı çalıştırdınız? Ben% 90-100 CPU kullanımı için oldukça fazla wallclock süresi almayı beklerdim - Windows kutumda GB başına yaklaşık 1 dakika çalışır, oysa Python gzip modülü GB başına 2 dakika alır. – Dave

cevap

10

ChristopheD'nin subprocess module kullanım önerisi bu soruya uygun bir cevaptır. Ancak, performans sorunlarınızı çözecek bana açık değil. Emin olmak için yeni kodun performansını ölçmek zorunda kalacaksınız. sen, sen POPEN nesnesinin stdin özelliğini kullanmayı düşünmelisiniz alt sürecine büyük miktarda veri göndermek gerekir yana

import subprocess 

p = subprocess.Popen("gzip -c > zipped.gz", shell=True, stdin=subprocess.PIPE) 
p.communicate("Hello World\n") 

:

sizin örnek kodu dönüştürün. Örneğin:

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 

Ayrıca this question faydalı görüşülecek bulabilirsiniz. Böyle

+0

1GB yüksek sıkıştırılabilir bir dosyada bu yöntemin% 33 daha hızlı olduğunu doğruladım. Bu gzip.open ile karşılaştırıldığında güzel bir gelişme. İşte bunu test etmek için kullanılan kod: ithalat alt işlemi text = "fjlaskfjioewru oijf alksfjlkqs jr jweqoirjwoiefjlkadsfj afjf \ n" xrange i için (1,25): metin + = metin p = subprocess.Popen ("gzip -c> zipped.gz", shell = True, stdin = altprocess.PIPE) p.stdin.write (metin) p.communicate() gzip zamanı.açık: 12.109u 1.194s 0: 13.37% 99,4 0 + 0k 0 + 0io 0PF + 0W zaman yukarıdaki kodu: 8.379u 2.602s 0: 10.17 107.8% 0 + 0k 0 + 0io 0PF + 0W – bu11d0zer

+0

Bu benim soruma iyi ve eksiksiz bir cevap. Teşekkürler. – bu11d0zer

+0

Favori cevabınızı kabul ettiğinizden emin olun :-). Hepimiz ekstra rep gibi. – Dave

2

olan resmi tek yönlü-to-do-it ve herhangi başka bir saf piton yaklaşımı daha hızlı gidecek düşüktür. Bu özellikle doğrudur, çünkü verilerinizin boyutu bellek içi seçenekleri dışlar. Büyük olasılıkla, en hızlı yol, tüm dosyayı diske yazmak ve bu dosyada gz'u aramak için subprocess'u kullanmaktır.

4

deneyin şey:

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

Bu cevap da iyi ve iyi çalışıyor. – bu11d0zer