2011-11-28 20 views
9

मैं यह पता लगाने कैसे पायथन में संपीड़ित फ़ाइल नीचे दी गई दो लाइनर के समान करने के लिए फ़ाइल आउटपुट लिखने की जरूरत का उपयोग कर पर्ल में gzip के लिए , यह "zipped.gz" फ़ाइल में ज़िपपीड फ़ाइलहेडल को जो कुछ भी प्रिंट करता है उसे संपीड़ित करने के लिए यूनिक्स gzip का उपयोग करता है।अजगर बराबर एक पाइप

मुझे पता है कि "आयात gzip" का उपयोग करने के लिए इस तरह अजगर में यह करने के लिए:

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

हालांकि, कि बेहद धीमी गति से होता है। प्रोफाइलर के मुताबिक, उस विधि का उपयोग करके मेरे रन टाइम का 9 0% हिस्सा लगता है क्योंकि मैं 200 जीबी असम्पीडित डेटा को विभिन्न आउटपुट फाइलों में लिख रहा हूं। मुझे पता है कि फाइल सिस्टम यहां समस्या का हिस्सा हो सकता है, लेकिन मैं इसके बजाय यूनिक्स/लिनक्स संपीड़न का उपयोग कर इसे रद्द करना चाहता हूं। यह आंशिक रूप से है क्योंकि मैंने सुना है कि इस मॉड्यूल का उपयोग करके डिकंप्रेसिंग भी धीमी है।

+1

आप इसे शुद्ध पायथन में किया की जरूरत है, या आप अपने फाइल सिस्टम पर एक द्विआधारी में एक कॉल के लिए समझौता कर सकता है (पायथन में, आप उपप्रक्रिया मॉड्यूल का उपयोग चाहते हैं)? – ChristopheD

+0

मैं इसे पायथन में नहीं करना पसंद करता क्योंकि शुद्ध पायथन विधियां बहुत धीमी हैं। – bu11d0zer

+0

क्या आपने अपने 200 जीबी असम्पीडित डेटा पर शैल से gzip प्रोग्राम चलाया है? मैं उम्मीद करता हूं कि 9 0-100% सीपीयू उपयोग पर वॉलक्लॉक समय का थोड़ा सा हिस्सा लें - मेरे विंडोज बॉक्स पर यह प्रति जीबी लगभग 1 मिनट चलता है, जबकि पायथन जीजीआईपी मॉड्यूल प्रति जीबी लगभग 2 मिनट लेता है। – Dave

उत्तर

10

subprocess module का उपयोग करने के क्रिस्टोफ़ेड के सुझाव इस प्रश्न का उचित उत्तर है। हालांकि, यह मुझे स्पष्ट नहीं है कि यह आपकी प्रदर्शन समस्याओं को हल करेगा। सुनिश्चित करने के लिए आपको नए कोड के प्रदर्शन को मापना होगा। जब से तुम सब-प्रक्रिया के लिए डेटा की बड़ी मात्रा को भेजने के लिए, आप popen वस्तु की stdin विशेषता का उपयोग पर विचार करना चाहिए की जरूरत है

import subprocess 

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

:

अपने नमूना कोड को बदलने के लिए। उदाहरण के लिए:

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 

तुम भी this question उपयोगी पर चर्चा मिल सकता है।

+0

मैंने सत्यापित किया कि 1 जीबी अत्यधिक संपीड़ित फ़ाइल पर यह विधि 33% तेज है। Gzip.open की तुलना में यह एक अच्छा सुधार है। यहाँ कोड मैं इसे परीक्षण के लिए किया गया है: आयात उपप्रक्रिया पाठ = "fjlaskfjioewru oijf alksfjlkqs JR jweqoirjwoiefjlkadsfj afjf \ n" xrange में मैं के लिए (1,25): पाठ + = पाठ पी = subprocess.Popen ("gzip -c> zipped.gz", खोल = सही, stdin = subprocess.PIPE) ' p.stdin.write (टेक्स्ट) p.communicate() gzip के लिए समय।खोलें: 12.109u 1.194s 0: 13.37 99.4% 0 + 0 हजार 0 + 0io 0pf + 0W समय उपरोक्त कोड के लिए: 8.379u 2.602s 0: 10.17 107.8% 0 + 0 हजार 0 + 0io 0pf + 0W – bu11d0zer

+0

यह मेरे प्रश्न का एक अच्छा और पूरा जवाब है। धन्यवाद। – bu11d0zer

+0

अपने पसंदीदा उत्तर को स्वीकार करना सुनिश्चित करें :-)। हम सभी को अतिरिक्त प्रतिनिधि पसंद है। – Dave

2

gzip module का उपयोग करना है सरकारी वन-वे-टू-do-यह और यह संभावना नहीं है कि किसी भी अन्य शुद्ध अजगर दृष्टिकोण तेजी से जाना जाएगा। यह विशेष रूप से सच है क्योंकि आपके डेटा का आकार स्मृति विकल्पों में नियम बनाता है। सबसे अधिक संभावना है कि डिस्क पर पूर्ण फ़ाइल लिखना सबसे तेज़ तरीका है और उस फ़ाइल पर gz पर कॉल करने के लिए subprocess का उपयोग करें।

4

इस तरह की कोशिश कुछ:

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

यह उत्तर भी अच्छा है और ठीक काम करता है। – bu11d0zer

संबंधित मुद्दे