पाइथन 2.7 में सबप्रोसेस के आउटपुट को कैसे छिपाएं


283

मैं Ubuntu पर eSpeak का उपयोग कर रहा हूं और एक पायथन 2.7 स्क्रिप्ट है जो प्रिंट करता है और एक संदेश बोलता है:

import subprocess
text = 'Hello World.'
print text
subprocess.call(['espeak', text])

eSpeak वांछित ध्वनियों का उत्पादन करता है, लेकिन शेल को कुछ त्रुटियों के साथ बंद कर देता है (ALSA lib ..., कोई सॉकेट कनेक्ट नहीं) इसलिए मैं आसानी से नहीं पढ़ सकता कि पहले क्या छपा था। बाहर निकलें कोड 0 है।

दुर्भाग्यवश इसकी वाचालता को बंद करने के लिए कोई प्रलेखित विकल्प नहीं है, इसलिए मैं केवल इसे नेत्रहीन रूप से मौन करने का रास्ता खोज रहा हूं और आगे की बातचीत के लिए खुले खोल को साफ रखना चाहता हूं।

मैं यह कैसे कर सकता हूँ?


क्या आप तब os.system के साथ कॉल नहीं कर सकते थे? आदर्श नहीं है, लेकिन न तो मुझे लगता है कि प्रिंट होना चाहिए
जोरन Beasley

@JoranBeasley: os.system () कंसोल को तब तक प्रिंट करेगा जब तक आप शेल कमांड को रीडायरेक्ट नहीं करते हैं
jd

नहीं, os.system ('जासूसी' + पाठ) इस व्यवहार को पुन: पेश करता है।
रिपेल

@ferkulat: मैंने os.systemसिंटैक्स दिखाने के लिए अपना जवाब अपडेट किया । हालांकि यह सिर्फ दृष्टांत के लिए है।
सबप्रोसेस के

2
गैर 2.7 विशिष्ट संस्करण: stackoverflow.com/questions/5495078/… जो सही subprocess.DEVNULसमाधान के लिए अनुमति देता है ।
सिरो सेंटिल्ली 郝海东 冠状 iro i 法轮功 '

जवाबों:


426

आउटपुट को DEVNULL पर पुनर्निर्देशित करें:

import os
import subprocess

FNULL = open(os.devnull, 'w')
retcode = subprocess.call(['echo', 'foo'], stdout=FNULL, stderr=subprocess.STDOUT)

यह इस शेल कमांड को चलाने के समान प्रभावी है:

retcode = os.system("echo 'foo' &> /dev/null")

50
माइक्रो नीट पिक्स: os.devnullयदि आप subprocess.DEVNULLउपलब्ध नहीं हैं तो आप उपयोग कर सकते हैं (<3.3), check_call()इसके बजाय का उपयोग करें call()यदि आप इसके लौटे हुए कोड की जांच नहीं करते हैं, तो बाइनरी मोड में फ़ाइलों को खोलें stdin/stdout/stderr, उपयोग के os.system()लिए हतोत्साहित होना चाहिए, उबंटू पर &>काम नहीं करता है shस्पष्ट >/dev/null 2>&1इस्तेमाल किया जा सकता है।
JFS

1
@JFSebastian: सुझाव के लिए धन्यवाद। मैं वास्तव में उपयोग करने के लिए था, os.devnullलेकिन गलती से इसे टाइप किया। इसके अलावा, मैं ओपी के उपयोग के साथ चिपका रहा हूं callक्योंकि वे संभावित अपवाद को नहीं पकड़ रहे हैं check_call। और os.systemपुनर्निर्देशित के लिए, यह सिर्फ एक उदाहरण था कि उपप्रोसेस दृष्टिकोण का प्रभावी उपयोग क्या कर रहा है। वास्तव में दूसरे सुझाव के रूप में नहीं।
१३:१३ बजे jdi

13
क्या आपको अपने द्वारा खोले गए FNULL को बंद करने की आवश्यकता नहीं है?
वैल

13
बस एक ध्यान दें, आप उपयोग कर सकते close_fds=Trueमें subprocess.callबंद करने के लिए FNULLवर्णनकर्ता के बाद उपप्रक्रिया मौजूद है
ewino

7
@ewino: पर close_fds=True, फ़ाइल वर्णनकर्ता बंद हो जाती हैं के बाद fork() , लेकिन पहले execvp() यानी, वे में बंद हो जाती हैं बच्चे प्रक्रिया अभी से पहले निष्पादन चलाया जाता है। close_fds=Trueयदि स्ट्रीम में से कोई भी पुनर्निर्देशित हो, तो विंडोज पर काम नहीं करेगामूल प्रक्रिया close_fdsमें फ़ाइलें बंद नहीं करता है।
jfs

89

यहां एक अधिक पोर्टेबल संस्करण है (सिर्फ मनोरंजन के लिए, यह आपके मामले में आवश्यक नहीं है):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT

try:
    from subprocess import DEVNULL # py3k
except ImportError:
    import os
    DEVNULL = open(os.devnull, 'wb')

text = u"René Descartes"
p = Popen(['espeak', '-b', '1'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
p.communicate(text.encode('utf-8'))
assert p.returncode == 0 # use appropriate for your program error handling here

4
ध्यान दें कि यह उत्पादन करता है DEVNULLजो पूरी तरह से सामान्य नहीं है, जैसे कि जो प्रदान किया गया है subprocess; जब से इसे खोला गया है wbइसका उपयोग नहीं किया जा सकता है stdin
रीड करें

1
@ रीड: आप 'r+b'मोड का उपयोग कर सकते हैं यदि आपको इसके बजाय आवश्यकता हो।
जफ्स

28

उपयोग subprocess.check_output(अजगर 2.7 में नया)। यदि यह विफल हो जाता है तो यह स्टैडआउट को दबा देगा और अपवाद को बढ़ा देगा। (यह वास्तव में स्टडआउट की सामग्री लौटाता है, इसलिए यदि आप चाहें तो बाद में अपने कार्यक्रम में इसका उपयोग कर सकते हैं।) उदाहरण:

import subprocess
try:
    subprocess.check_output(['espeak', text])
except subprocess.CalledProcessError:
    # Do something

आप stderr को भी दबा सकते हैं:

    subprocess.check_output(["espeak", text], stderr=subprocess.STDOUT)

2.7 से पहले के लिए, का उपयोग करें

import os
import subprocess
with open(os.devnull, 'w')  as FNULL:
    try:
        subprocess._check_call(['espeak', text], stdout=FNULL)
    except subprocess.CalledProcessError:
        # Do something

यहां, आप stderr को दबा सकते हैं

        subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL)

अधिक सटीक रूप से, यह स्टडआउट लौटाता है। जो बहुत अच्छा है और इसे इग्नोर करने में सक्षम होने के अलावा इसे इस्तेमाल करना चाहते हैं।
सिरो सेंटिल्ली 郝海东 冠状 iro 事件 法轮功 '

मुझे लगता है कि यह अधिक सीधा है। @StudentT मुझे लगता है कि आपको CalledProcessError के साथ त्रुटियों को संभालना चाहिए। except subprocess.CalledProcessError as eऔर उसके बाद का उपयोग e.codeयाe.output
रॉड्रिगो ई प्रिंसिपे

21

Python3 के रूप में आपको अब devnull खोलने की आवश्यकता नहीं है और आप subprocess.DEVNULL पर कॉल कर सकते हैं ।

आपका कोड इस प्रकार अपडेट किया जाएगा:

import subprocess
text = 'Hello World.'
print(text)
subprocess.call(['espeak', text], stderr=subprocess.DEVNULL)

काम करता है! इसके अलावा, स्वैप कर सकते हैं stderrके साथ stdoutदबाने आउटपुट से (एक और तर्क के रूप में या संलग्न) उपरोक्त कोड में। "आउटपुट" सवाल के शीर्षक में है और जो मुझे यहां ले जाता है ... शायद तुच्छ, लेकिन सोचा कि यह ध्यान देने योग्य था।
ThatsRightJack

-7

इसके बजाय आज्ञाओं का उपयोग क्यों न करें ।getoutput ()?

import commands

text = "Mario Balotelli" 
output = 'espeak "%s"' % text
print text
a = commands.getoutput(output)

ए) यह इनपुट को नहीं छोड़ता है, यह इसे अनावश्यक रूप से मेमोरी में जमा करता है बी) यह टूट जाता है अगर textइसमें उद्धरण हैं, या एक अलग वर्ण एन्कोडिंग का उपयोग करता है, या कमांड लाइन के लिए बहुत बड़ा है c) यह केवल यूनिक्स है (पायथन 2 पर)
10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.