2009-03-06 26 views
2

Gzip, uuencode ve standart çıktıya yazdırmak istediğim bazı verilerim var. Ne temelde var olan:Python Popen, akışları ve çoklu işlemleri kapatma

compressor = Popen("gzip", stdin = subprocess.PIPE, stdout = subprocess.PIPE) 
encoder = Popen(["uuencode", "dummy"], stdin = compressor.stdout) 

Ben kompresöre verileri beslemek yolu compressor.stdin.write (malzeme) geçer.

Gerçekten yapmam gereken şey, kompresöre bir EOF göndermek ve bunu nasıl yapacağımı bilmiyorum.

Bir noktada compressor.stdin.close() yöntemini denedim, ancak çalışmıyor - kompresör doğrudan bir dosyaya yazdığında iyi çalışıyor, ancak yukarıdaki durumda işlem sonlanmıyor ve compressor.wait() üzerinde duruyor.

Öneriler? Bu durumda, gzip bir örnektir ve gerçekten bir işlemin çıktısını başka bir şeye iletmek için bir şeyler yapmam gerekiyor.

Not: Sıkıştırmam gereken veriler belleğe sığmayacak, bu nedenle iletişim burada gerçekten iyi bir seçenek değil. Ayrıca, sadece yukarıdaki 2 satırdan sonra

compressor.communicate("Testing") 

çalıştırırsanız, hala zlib kullanılarak düşünün hata

 
    File "/usr/lib/python2.4/subprocess.py", line 1041, in communicate 
    rlist, wlist, xlist = select.select(read_set, write_set, []) 
+0

Cobbal'ın cevabı gzip için çalışacak olsa da, bu aslında sadece bir örnektir - borulara ihtiyacım var ... – bsdfish

cevap

4

Sorunun, boruyu açtığınız sırayla olduğunu sanıyorum. UUEncode komiktir, sadece doğru yoldan gelen bir boru yoksa fırlatılacağınız zaman (sadece stip ve stdout olarak sadece BIPE ile patlamayı görmek için bir Popen çağrısında kendi başındaki şeyi başlatmayı deneyin)

bu deneyin:

encoder = Popen(["uuencode", "dummy"], stdin=PIPE, stdout=PIPE) 
compressor = Popen("gzip", stdin=PIPE, stdout=encoder.stdin) 

compressor.communicate("UUencode me please") 
encoded_text = encoder.communicate()[0] 
print encoded_text 

begin 644 dummy 
F'XL(`%]^L$D``PL-3<U+SD])5<A-52C([email protected]`;2O+"!(````` 
` 
end 

Haklısınız, btw ... bir boru genel EOF aşağı göndermek için bir yolu yoktur. Sonuçta, her program kendi EOF'unu gerçekten tanımlar. Bunu yapmanın yolu, yapmaya çalıştığınız gibi boruyu kapatmaktır.

DÜZENLEME: Uuencode hakkında daha açık olmalıyım.Bir kabuk programı olarak, varsayılan davranış konsol girişini beklemektir. "Canlı" gelen boru olmadan çalıştırırsanız, konsol girişi için beklemeyi engeller. Enkoder ikincisini açarak, kompresör borusunu aşağı indirmeden önce, kodlayıcı yazarak yazmaya başlamanızı engellemekteydi. Jerub haklıydı, engelleyen bir şey vardı.

+0

maalesef() okumayı denerseniz, tüm çıktının bellekte depolanmasını gerektirir. kodlayıcının stdout'u hala görünmektedir – cobbal

+0

Stdout'u okumamasanız da, communications() 'ı kullanma. Stdout içeriği, iletişim komutundan stdin ile tuple döndürülür. Yazıları kullanmak ve her iki boruyu okumak için bunu değiştirebilirsiniz, ancak python dokümanlarının buna karşı önerdiği monkut'tan gelen yorumu görün. –

+0

Bazı büyük verileriniz varsa, kabuk süreçleri arasında iletişim kurmak için geçici dosyaları kullanmak belki en iyisi olur mu? –

1

sadece sıkıştırmak istiyorum ve dosya sarmalayıcılarını gerekmiyorsa ile asılı modül

import zlib 
compressed = zlib.compress("text") 

Kabuk = True ve unix borularının önerileri neden çalışmaz?

from subprocess import * 

pipes = Popen("gzip | uuencode dummy", stdin=PIPE, stdout=PIPE, shell=True) 
for i in range(1, 100): 
    pipes.stdin.write("some data") 
pipes.stdin.close() 
print pipes.stdout.read() 

Bu piton doğrudan yapması gereken türden bir şey değildir

3

iş gibi görünüyor, bir kabuk ile bunu yapmak için çok daha iyi bir fikirdir yapmak nasıl bir şey çalışmalarla ilgili dışmerkezlikler vardır . Altprocess.Popen ("foo | bar", shell = True) 'i kullanabiliyorsanız, o zaman daha iyisi.

Olanak şu olabilir: gzip'in henüz tüm girdilerinin çıktısını almadı ve işlem, stdout yazmaları bitinceye kadar çıkmayacak.

Strace kullanıyorsanız, hangi sistemin sistem çağrısının engellendiğini görebilirsiniz. Hangi işlemin gzip işlemi olduğunu öğrenmek için ps auxwf'u kullanın ve ardından hangi sistemin çalıştığını görmek için strace -p $pidnum kullanın. Stdin'in FD 0 ve stdout'un FD 1 olduğunu unutmayın, muhtemelen bu dosya tanıtıcılarını okuduğunuzu veya yazdığını göreceksiniz.

İlgili konular