[python] 파이썬에서 stdout을 “nothing”으로 리디렉션

나는 충분히 많은 수의 모듈로 구성된 큰 프로젝트를 가지고 있으며, 각각은 표준 출력으로 무언가를 인쇄합니다. 이제 프로젝트의 규모가 커짐에 따라 더 큰 프로젝트가 없습니다. 의print 상당히 느린 프로그램을 만들었습니다 표준 출력에 많이 인쇄 문.

따라서 런타임 에 stdout에 아무것도 인쇄할지 여부 를 결정하려고합니다 . 모듈이 많기 때문에 모듈을 변경할 수 없습니다. (stdout을 파일로 리디렉션 할 수는 있지만 상당히 느립니다.)

그래서 내 질문은 어떻게 stdout을 아무것도로 리디렉션하지 않는 것입니다. 즉, 어떻게 print진술이 아무것도하지 않게합니까?

# I want to do something like this.
sys.stdout = None         # this obviously will give an error as Nonetype object does not have any write method.

현재 내가 가진 유일한 아이디어는 write 메소드 (아무것도하지 않음)가있는 클래스를 만들고 stdout 을이 클래스의 인스턴스로 리디렉션하는 것입니다.

class DontPrint(object):
    def write(*args): pass

dp = DontPrint()
sys.stdout = dp

파이썬에 내장 메커니즘이 있습니까? 아니면 이것보다 더 좋은 것이 있습니까?



답변

크로스 플랫폼 :

import os
import sys
f = open(os.devnull, 'w')
sys.stdout = f

Windows에서 :

f = open('nul', 'w')
sys.stdout = f

Linux에서 :

f = open('/dev/null', 'w')
sys.stdout = f


답변

이 작업을 수행하는 좋은 방법은 인쇄물을 감쌀 작은 컨텍스트 프로세서를 만드는 것입니다. with 하여 모든 출력을 침묵시킵니다.

파이썬 2 :

import os
import sys
from contextlib import contextmanager

@contextmanager
def silence_stdout():
    old_target = sys.stdout
    try:
        with open(os.devnull, "w") as new_target:
            sys.stdout = new_target
            yield new_target
    finally:
        sys.stdout = old_target

with silence_stdout():
    print("will not print")

print("this will print")

파이썬 3.4+ :

Python 3.4에는 이와 같은 컨텍스트 프로세서가 있으므로 간단히 다음과 같이 contextlib를 사용할 수 있습니다.

import contextlib

with contextlib.redirect_stdout(None):
    print("will not print")

print("this will print")

이 코드를 실행하면 첫 번째 출력이 아닌 두 번째 출력 행만 인쇄됩니다.

$ python test.py
this will print

이것은 크로스 플랫폼 (Windows + Linux + Mac OSX)에서 작동하며 다른 답변보다 깨끗합니다.


답변

Python 3.4 이상인 경우 표준 라이브러리를 사용하는 간단하고 안전한 솔루션이 있습니다.

import contextlib

with contextlib.redirect_stdout(None):
  print("This won't print!")


답변

(적어도 내 시스템에서는) os.devnull에 쓰는 것이 DontPrint 클래스에 쓰는 것보다 약 5 배 빠릅니다.

#!/usr/bin/python
import os
import sys
import datetime

ITER = 10000000
def printlots(out, it, st="abcdefghijklmnopqrstuvwxyz1234567890"):
   temp = sys.stdout
   sys.stdout = out
   i = 0
   start_t = datetime.datetime.now()
   while i < it:
      print st
      i = i+1
   end_t = datetime.datetime.now()
   sys.stdout = temp
   print out, "\n   took", end_t - start_t, "for", it, "iterations"

class devnull():
   def write(*args):
      pass


printlots(open(os.devnull, 'wb'), ITER)
printlots(devnull(), ITER)

다음과 같은 결과를 얻었습니다.

<open file '/dev/null', mode 'wb' at 0x7f2b747044b0>
   took 0:00:02.074853 for 10000000 iterations
<__main__.devnull instance at 0x7f2b746bae18>
   took 0:00:09.933056 for 10000000 iterations


답변

Unix 환경 (Linux 포함)에있는 경우 출력을 /dev/null다음으로 리디렉션 할 수 있습니다 .

python myprogram.py > /dev/null

그리고 Windows의 경우 :

python myprogram.py > nul


답변

이건 어때요:

from contextlib import ExitStack, redirect_stdout
import os

with ExitStack() as stack:
    if should_hide_output():
        null_stream = open(os.devnull, "w")
        stack.enter_context(null_stream)
        stack.enter_context(redirect_stdout(null_stream))
    noisy_function()

이것은 contextlib 모듈 의 기능을 사용 하여 결과에 따라 실행하려는 모든 명령의 출력을 숨 깁니다.should_hide_output() 해당 기능이 실행 된 후 출력 동작을 복원합니다.

당신은 표준 오류 출력을 숨기려면 다음 가져올 redirect_stderr에서 contextlib하고 말하는 줄을 추가stack.enter_context(redirect_stderr(null_stream)) .

주요 단점은 이것이 Python 3.4 이상 버전에서만 작동한다는 것입니다.


답변

클래스는 잘 작동합니다 ( write()메소드 이름을 제외하고 – write()소문자 로 호출해야 함 ). 그냥 사본을 저장하십시오sys.stdout다른 변수에 .

* NIX를 사용하는 경우 할 수 sys.stdout = open('/dev/null')있지만 자신의 클래스를 롤링하는 것보다 이식성이 떨어집니다.