Python 2.7에서 하위 프로세스의 출력을 숨기는 방법


283

우분투에서 eSpeak를 사용하고 있으며 메시지를 인쇄하고 말하는 Python 2.7 스크립트가 있습니다.

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

eSpeak는 원하는 사운드를 생성하지만 일부 오류 (ALSA lib ..., 소켓 연결 없음)로 쉘을 어지럽히므로 이전에 인쇄 된 내용을 쉽게 읽을 수 없습니다. 종료 코드는 0입니다.

불행히도 자세한 설명을 해제 할 수있는 문서화 된 옵션이 없으므로 시각적으로 만 침묵시키고 추가 상호 작용을 위해 열린 껍질을 깨끗하게 유지하는 방법을 찾고 있습니다.

어떻게해야합니까?


os.system으로 전화 할 수 없습니까? 하지 이상적인하지만 난 생각 해달라고 인쇄 야해
Joran 비즐리

@JoranBeasley : 쉘 명령을 재지 정하지 않는 한 os.system ()은 콘솔에 출력됩니다
jdi

아니요, os.system ( 'espeak'+ text)는이 동작을 재현합니다.
rypel

@ferkulat : os.system구문을 보여주기 위해 대답을 업데이트했습니다 . 그것은 단지 설명을위한 것이지만. 하위 프로세스에
충실

2
2.7이 아닌 특정 버전 : stackoverflow.com/questions/5495078/… 완벽한 subprocess.DEVNUL솔루션을 제공합니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

답변:


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 2016 년

1
@JFSebastian : 제안 해 주셔서 감사합니다. 나는 실제로 사용 os.devnull하려고했지만 실수로 입력했습니다. 또한 call가능한 예외를 잡을 수 없기 때문에 OP의 사용을 고수 하고 있습니다 check_call. 그리고 대한 os.system리디렉션, 그것은 서브 프로세스 접근 방법의 효과적인 사용하고있는 것을 더 많이 단지 그림이었다. 실제로 두 번째 제안은 아닙니다.
jdi

13
열었던 FNULL을 닫을 필요가 없습니까?
Val

13
참고로, 서브 프로세스가 존재하는 후에 close_fds=Truein subprocess.call을 사용 하여 FNULL디스크립터 를 닫을 수 있습니다
ewino

7
@ewino :에 close_fds=True, 파일 기술자가 닫힌 fork() 하지만 전에 execvp() 즉, 그들이 폐쇄되는 자식 바로 처리 하기 전에 실행 파일이 실행됩니다. close_fds=True스트림 중 하나라도 리디렉션되면 Windows에서 작동하지 않습니다 . 부모 프로세스 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
@Reid : 'r+b'대신 필요한 경우 모드를 사용할 수 있습니다 .
jfs

28

사용하십시오 subprocess.check_output(파이썬 2.7의 새로운 기능). 명령이 실패하면 stdout을 억제하고 예외를 발생시킵니다. (실제로 stdout의 내용을 반환하므로 원하는 경우 나중에 프로그램에서 사용할 수 있습니다.) 예 :

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)

보다 정확하게는 stdout을 반환합니다. 그것을 무시할 수있을뿐만 아니라 사용하고 싶을만큼 훌륭합니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

나는 이것이 더 간단하다고 생각합니다. @StudentT CalledProcessError로 오류를 처리해야한다고 생각합니다. except subprocess.CalledProcessError as e그리고e.codee.output
Rodrigo E. Principe

21

Python3부터 더 이상 devnull을 열 필요가 없으며 subprocess.DEVNULL 을 호출 할 수 있습니다 .

코드는 다음과 같이 업데이트됩니다.

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

공장! 또한, 교환 수 stderrstdout억제 출력에 (또는 다른 인자로 APPEND) 위의 코드이다. "출력"은 질문의 제목에 있으며 여기로 나를 인도하는 것은 사소한 일이지만 언급 할 가치가 있다고 생각했습니다.
ThatsRightJack

-7

대신 commands.getoutput ()을 사용하지 않는 이유는 무엇입니까?

import commands

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

a) 입력을 버리지 않고 메모리에 불필요하게 축적합니다 .b) text따옴표가 있거나 다른 문자 인코딩을 사용하거나 명령 줄에 너무 큰 경우 c) 유닉스 전용입니다 (파이썬 2)
jfs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.