prosource

python에서 stdout을 "nothing"으로 리디렉션

probook 2023. 7. 22. 10:11
반응형

python에서 stdout을 "nothing"으로 리디렉션

저는 충분한 수의 모듈로 구성된 대규모 프로젝트를 가지고 있으며, 각 모듈은 표준 출력에 맞게 인쇄됩니다.이제 프로젝트의 규모가 커짐에 따라 다음과 같은 많은 수가 있습니다.printstd out에서 많이 출력되는 문들은 프로그램을 상당히 느리게 만들었습니다.

그래서 저는 이제 런타임에 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.

현재 제가 가지고 있는 유일한 아이디어는 쓰기 방법(아무것도 하지 않음)이 있는 클래스를 만들고 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")

None(없음)을 리디렉션 대상으로 사용하여 sys.stdout에 직접 쓰기를 억제하려는 코드는 작동하지 않습니다.대신 다음을 사용할 수 있습니다.

import contextlib
import sys
import os

with contextlib.redirect_stdout(open(os.devnull, 'w')):
    sys.stdout.write("will not print")

sys.stdout.write("this will print")

코드가 stdout 대신 stderr에 쓰는 경우 redirect_stdout 대신 contextlib.redirect_stderr을 사용할 수 있습니다.


이 코드를 실행하면 출력의 두 번째 줄만 인쇄되고 첫 번째 줄은 인쇄되지 않습니다.

$ python test.py
this will print

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

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

import contextlib

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

(적어도 내 시스템에서는) tos.devnull을 쓰는 것이 돈트프린트 클래스에 쓰는 것보다 약 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

그냥 조롱해도 돼요.

import mock

sys.stdout = mock.MagicMock()

리소스 할당을 처리하거나 자신의 클래스를 롤링하지 않으려면 다음을 사용할 수 있습니다.TextIOPython 타이핑에서.기본적으로 필요한 모든 메서드가 스텁됩니다.

import sys
from typing import TextIO

sys.stdout = TextIO()

당신의 수업은 잘 될 것입니다. (을 제외하고)write() 이름 메드이름 - 호야합다니라고 .write()소문자).의 복사본을 저장해야 합니다.sys.stdout다른 변수에서.

은 *NIX를 하실 수 .sys.stdout = open('/dev/null')하지만 이것은 당신의 수업을 굴리는 것보다 휴대성이 떨어집니다.

이거 어때:

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()그런 다음 해당 기능이 실행된 후 출력 동작을 복원합니다.

출력을 import를 수행합니다.redirect_stderrcontextlib그리고 다음과 같은 말을 덧붙입니다.stack.enter_context(redirect_stderr(null_stream)).

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

sys.stdout = None

괜요아에 .print()case. sys할 수 를 들어 case. 그러나 sys.stdout 등의 메서드를 호출하면 오류가 발생할 수 있습니다.sys.stdout.write().

문서에는 다음과 같은 참고 사항이 있습니다.

일부 조건에서는 stdin, stdout 및 stderr과 원래stdin, stdout 및 stderr이 None일 수 있습니다.일반적으로 콘솔에 연결되지 않은 Windows GUI 앱과 Python w로 시작된 Python 앱의 경우입니다.

iFreilicht의 답변에 대한 보충 - Python 2와 3 모두에 대해 작동합니다.

import sys

class NonWritable:
    def write(self, *args, **kwargs):
        pass

class StdoutIgnore:
    def __enter__(self):
        self.stdout_saved = sys.stdout
        sys.stdout = NonWritable()
        return self

    def __exit__(self, *args):
        sys.stdout = self.stdout_saved

with StdoutIgnore():
    print("This won't print!")

흐름에는 여러 가지 좋은 답변이 있지만, 여기 제 파이썬 3 답변이 있습니다(sys.stdout일 때).fileno(파일)는 더 이상 지원되지 않습니다):

import os
import sys
oldstdout = os.dup(1)
oldstderr = os.dup(2)
oldsysstdout = sys.stdout
oldsysstderr = sys.stderr

# Cancel all stdout outputs (will be lost) - optionally also cancel stderr
def cancel_stdout(stderr=False):
    sys.stdout.flush()
    devnull = open('/dev/null', 'w')
    os.dup2(devnull.fileno(), 1)
    sys.stdout = devnull
    if stderr:
        os.dup2(devnull.fileno(), 2)
        sys.stderr = devnull

# Redirect all stdout outputs to a file - optionally also redirect stderr
def reroute_stdout(filepath, stderr=False):
    sys.stdout.flush()
    file = open(filepath, 'w')
    os.dup2(file.fileno(), 1)
    sys.stdout = file
    if stderr:
        os.dup2(file.fileno(), 2)
        sys.stderr = file

# Restores stdout to default - and stderr
def restore_stdout():
    sys.stdout.flush()
    sys.stdout.close()
    os.dup2(oldstdout, 1)
    os.dup2(oldstderr, 2)
    sys.stdout = oldsysstdout
    sys.stderr = oldsysstderr

사용 방법:

  • 다음을 사용하여 모든 stdout 및 stderr 출력을 취소합니다.

    cancel_stdout(stderr=True)

  • 모든 stdout(stderr은 아님)을 파일로 라우팅합니다.

    reroute_stdout("output.txt')

  • stdout 및 stderr 복원하기

    restore_stdout 설정

이것을 시도해 보는 게 어때요?

sys.stdout.close()
sys.stderr.close()

다음과 같은 다양한 답변에 몇 가지 예를 추가합니다.

import argparse
import contextlib

class NonWritable:
    def write(self, *args, **kwargs):
        pass

parser = argparse.ArgumentParser(description='my program')
parser.add_argument("-p", "--param", help="my parameter", type=str, required=True)

#with contextlib.redirect_stdout(None): # No effect as `argparse` will output to `stderr`
#with contextlib.redirect_stderr(None): # AttributeError: 'NoneType' object has no attribute 'write'
with contextlib.redirect_stderr(NonWritable): # this works!
    args = parser.parse_args()

일반 출력은 다음과 같습니다.

>python TEST.py
usage: TEST.py [-h] -p PARAM
TEST.py: error: the following arguments are required: -p/--param

저는 이거 써요.stdout나중에 무시하는 문자열로 이동합니다.컨텍스트 관리자를 사용하여 원래 설정을 저장하고 복원합니다.stdout.

from io import StringIO
...
with StringIO() as out:
    with stdout_redirected(out):
        # Do your thing

stdout_redirected다음과 같이 정의됩니다.

from contextlib import contextmanager

@contextmanager
def stdout_redirected(new_stdout):
    save_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout = save_stdout

언급URL : https://stackoverflow.com/questions/6735917/redirecting-stdout-to-nothing-in-python

반응형