2012-05-07 20 views
8

मैं अजगर में एक शेल स्क्रिप्ट को कॉल करने का प्रयास कर रहा हूं, लेकिन यह टूटी हुई पाइप त्रुटि की रिपोर्ट करता रहता है (परिणाम ठीक है, लेकिन मैं एसटीडीईआरआर में त्रुटि संदेश नहीं देखना चाहता)। मैं कारण केंद्रित है, और यह निम्नलिखित स्निपेट के रूप में reproduced किया जा सकता है:पायथन: subprocess.call टूटा हुआ पाइप

subprocess.call('cat /dev/zero | head -c 10 | base64', shell=True)

AAAAAAAAAAAAAA ==

बिल्ली: लिखने त्रुटि: टूटी पाइप

/dev/zero, एक अनंत धारा है, लेकिन head -c 10 केवल 10 बाइट्स पढ़ता है और बाहर निकलता है, तो पीयर ने पाइप बंद कर दिया है, इसलिए बिल्ली को सिगिपिप मिलेगा। जब मैं खोल में कमांड चलाता हूं तो कोई टूटा हुआ पाइप त्रुटि संदेश नहीं होता है, लेकिन पाइथन इसे क्यों दिखाता है?

+4

त्रुटि दूर चला जाता है जब आप को छोड़ [uuoc] https://en.wikipedia.org/wiki/:

त्रुटि संदेश cat से आप preexec_fn तर्क का उपयोग कर सकते subprocess.call करने से बचने के लिए Cat_% 28Unix% 29 # Useless_use_of_cat): 'subprocess.call ('head -c 10

+2

@ लार्समैन: आप इसे उत्तर के रूप में –

+0

@ChrisMorgan: वास्तव में, मैं दृढ़ता से आपका जवाब पसंद करता हूं। –

उत्तर

2

इस मामूली मामले में कम से कम आप शेल कमांड — का उपयोग करके कुछ भी प्राप्त नहीं कर रहे हैं और आप पोर्टेबिलिटी और गति खो रहे हैं।

अजगर 2 कोड:

>>> import base64 
>>> base64.b64encode(open('/dev/zero', 'rb').read(10)) 
'AAAAAAAAAAAAAA==' 
>>> base64.b64encode('\0' * 10) 
'AAAAAAAAAAAAAA==' 

अजगर 3 में (कोड भी 2.6+ में, चलेगा, हालांकि यह उदाहरणों str बल्कि bytes से वापस आ जाएगी):

>>> import base64 
>>> base64.b64encode(open('/dev/zero', 'rb').read(10)) 
b'AAAAAAAAAAAAAA==' 
>>> base64.b64encode(b'\0' * 10) 
b'AAAAAAAAAAAAAA==' 

प्रत्येक मामले में, पहला उदाहरण /dev/zero (स्वयं में गैर-पोर्टेबल, लेकिन कभी भी दिमाग में नहीं) का उपयोग बरकरार रखता है, दूसरा प्रभाव उत्पन्न करता है, हालांकि मुझे लगता है कि यह विशेष रूप से आप नहीं चाहते हैं?

+0

+1। '\ x00'' भी पायथन 3.x में '' \ 0'' (या 'बी' \ 0'' लिखा जा सकता है)। –

+1

'\ 0'' \ x00' से छोटा है, मुझे लगता है ... –

+0

मुझे लगता है कि मैं subdir का उत्तर पसंद करता हूं, जो सीधे प्रश्न को संबोधित करता है, और समस्या बताता है। –

6

सिगिप सिग्नल के लिए डिफ़ॉल्ट कार्रवाई प्रोग्राम को समाप्त करना है। पाइथन दुभाषिया इसे अपग्रेड के रूप में किसी प्रोग्राम में टूटी हुई पाइप त्रुटियों की रिपोर्ट करने में सक्षम होने के लिए SIG_IGN में बदल देता है।

जब आप cat ... |head ... खोल में निष्पादित करते हैं, cat में डिफ़ॉल्ट सिगिप हैंडलर है, और ओएस कर्नेल इसे सिगिप पर समाप्त कर देता है।

जब आप cat निष्पादित subprocess वह अपने माता-पिता (अजगर दुभाषिया) से SIGPIPE हैंडलर निकला है का उपयोग करते हुए, SIGPIPE सिर्फ नजरअंदाज कर दिया है और cat जाँच errno चर और मुद्रण त्रुटि संदेश द्वारा त्रुटि ही संभालती है। (

from signal import signal, SIGPIPE, SIG_DFL 
subprocess.call(
    'cat /dev/zero | head -c 10 | base64', 
    shell = True, 
    preexec_fn = lambda: signal(SIGPIPE, SIG_DFL) 
) 
+0

उत्कृष्ट, इसके लिए बहुत बहुत धन्यवाद, बिल्ली का उपयोग करके एक शेल स्क्रिप्ट के साथ मेरी समस्या हल हो गई (और मुझे पूरा यकीन है कि यह एक यूओयूक नहीं है, शायद यह एक और सवाल है!)। –

+0

वास्तव में उत्कृष्ट स्पष्टीकरण और समाधान। –

+0

बढ़िया! एक tr फिक्स्ड: subprocess.call() के साथ एक बैश स्क्रिप्ट को कॉल करने के कारण टूटी हुई पाइप त्रुटि – Hanynowsky

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