인쇄 호출을 차단하는 방법은 무엇입니까?


81

함수 호출을 중지하는 방법이 print있습니까?


pygame.joystick작업중인 게임에 모듈을 사용 하고 있습니다.

pygame.joystick.Joystick개체를 만들고 게임의 실제 루프에서 해당 멤버 함수 get_button를 호출하여 사용자 입력을 확인합니다. 이 함수는 필요한 모든 작업을 수행하지만 문제 print는를 호출 하여 게임 속도가 상당히 느려진다는 것입니다.

이 전화를 차단할 수 있습니까 print?

답변:


108

Python을 사용하면 모든 파일 객체로 표준 출력 (stdout)을 덮어 쓸 수 있습니다. 이것은 크로스 플랫폼에서 작동하고 null 장치에 기록되어야합니다.

import sys, os

# Disable
def blockPrint():
    sys.stdout = open(os.devnull, 'w')

# Restore
def enablePrint():
    sys.stdout = sys.__stdout__


print 'This will print'

blockPrint()
print "This won't"

enablePrint()
print "This will too"

한 함수가 인쇄되는 것을 원하지 않으면 그 blockPrint()전에 호출 enablePrint()하고 계속하려면 호출 하십시오 . 모든 인쇄 를 비활성화 하려면 파일 상단에서 차단을 시작하십시오.


23
이것은 나를 위해 영구적으로 차단 된 인쇄 인 것 같습니다. enablePrint로 복원되지 않음
Johnny V

10
이 솔루션은 Jupyter 세포에 제대로 인쇄 복원되지 않습니다
oski86

1
인쇄 할 인수가 여전히 평가되고 있으므로 모든 인쇄 줄을 수동으로 주석 처리 한 스크립트보다 시간이 더 오래 걸릴까요?
라디오 제어

79

@FakeRainBrigand 솔루션을 기반으로 더 안전한 솔루션을 제안합니다.

import os, sys

class HiddenPrints:
    def __enter__(self):
        self._original_stdout = sys.stdout
        sys.stdout = open(os.devnull, 'w')

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout.close()
        sys.stdout = self._original_stdout

그런 다음 다음과 같이 사용할 수 있습니다.

with HiddenPrints():
    print("This will not be printed")

print("This will be printed as before")

예외를 처리 할 때 특히 중요한 stdout을 다시 활성화하는 것을 잊을 수 없기 때문에 훨씬 안전합니다.

없이 with

다음 예제에서는 이전 답변에서 제안 된 인쇄 활성화 / 비활성화 기능을 사용합니다.

예외를 발생시킬 수있는 코드가 있다고 상상해보십시오. finally어떤 경우에도 인화를 가능하게 하려면 문 을 사용해야했습니다 .

try:
    disable_prints()
    something_throwing()
    enable_prints() # This will not help in case of exception
except ValueError as err:
    handle_error(err)
finally:
    enable_prints() # That's where it needs to go.

finally절 을 잊은 경우 print호출은 더 이상 아무것도 인쇄하지 않습니다.

with인쇄가 다시 활성화되도록 하는 문 을 사용하는 것이 더 안전합니다 .

참고 : sys.stdout = None누군가 다음과 같은 메서드를 호출 할 수 있으므로를 사용하는 것은 안전하지 않습니다.sys.stdout.write()


6
아주 좋은 해결책! 나는 방금 똑같은 것을 썼고 당신은 이미 그렇게 대답했다는 것을 발견했습니다 : D 왜 이것이 더 좋은 방법인지에 대한 약간의 정보를 추가하겠습니다.
iFreilicht 17.10.23

Noobie 질문 : 클래스를 종료 한 후 devnull을 close ()하는 것이 중요할까요?
jlsecrest

@Wadsworth, 나는 대답을 모른다. devnull의 속성은 제대로 닫힐 필요가 없다고 생각합니다. 그러나 리소스를 해제하려면 항상 열린 핸들러를 닫아야한다는 소문이 있습니다. 내가 아는 CPython은 가비지 수집기가 얻는 한 devnull 자체를 닫아야합니다.
Alexander Chzhen

2
나는 점점 된 ResourceWarning: unclosed file <_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>이 코드를 사용하는 경우 ( 'W', os.devnull) 대신 개방의 sys.stdout = 없음을 설정하지하여 해결,
WellDone2094

@ WellDone2094, 감사합니다. sys.stdout.close()이탈 방법을 추가 했습니다. 이것은 도움이 될 것입니다. 참고 sys.stdout = None누군가가 같은 표준 출력의 메소드를 호출 할 수 있기 때문에, 오류가 발생할 수 있습니다 sys.stdout.write().
Alexander Chzhen

33

@Alexander Chzhen이 제안했듯이 컨텍스트 관리자를 사용하는 것이 한 쌍의 상태 변경 함수를 호출하는 것보다 안전합니다.

그러나 컨텍스트 관리자를 다시 구현할 필요는 없습니다. 이미 표준 라이브러리에 있습니다. 당신은 리디렉션 할 수 있습니다 stdout(즉, 파일 객체 print와 용도) contextlib.redirect_stdout, 또한 stderr으로 contextlib.redirect_stderr.

import os
import contextlib

with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
    print("This won't be printed.")

7

특정 기능에 의한 인쇄 호출을 차단하려면 데코레이터를 사용하는 더 깔끔한 솔루션이 있습니다. 다음 데코레이터를 정의하십시오.

# decorater used to block function printing to the console
def blockPrinting(func):
    def func_wrapper(*args, **kwargs):
        # block all printing to the console
        sys.stdout = open(os.devnull, 'w')
        # call the method in question
        value = func(*args, **kwargs)
        # enable all printing to the console
        sys.stdout = sys.__stdout__
        # pass the return value of the method back
        return value

    return func_wrapper

그런 다음 @blockPrinting기능 앞에 배치 하십시오. 예를 들면 :

# This will print
def helloWorld():
    print("Hello World!")
helloWorld()

# This will not print
@blockPrinting
def helloWorld2():
    print("Hello World!")
helloWorld2()

2

아니요, 특히 대부분의 PyGame이 C로 작성되었습니다.

그러나이 함수가 print를 호출하면 PyGame 버그이므로보고 만하면됩니다.


2

나는 똑같은 문제가 있었고 다른 해결책으로 오지 않았지만 프로그램의 출력을 (stdout 또는 stderr에서 스팸이 ​​발생하는지 정확히 알지 못함) /dev/null너바나 로 리디렉션했습니다 .

사실, 그것은 오픈 소스이지만, 나는 pygame소스와 빌드 프로세스 에 뛰어 들어서 어떻게 든 디버그 스팸을 막을 만큼 열정적이지 않았습니다 .

편집하다 :

pygame.joystick모듈 에 대한 호출이 printf파이썬에 실제 값을 반환하는 모든 기능의를 :

printf("SDL_JoystickGetButton value:%d:\n", value);

불행히도 이것들을 주석 처리하고 전체를 다시 컴파일해야합니다. 아마도 제공된 setup.py것이 내가 생각했던 것보다 쉽게 ​​만들 것입니다. 시도해 볼 수 있습니다 ...


2

완전히 다른 접근 방식은 명령 줄에서 리디렉션하는 것입니다. Windows를 사용하는 경우 이는 배치 스크립트를 의미합니다. Linux에서는 bash.

/full/path/to/my/game/game.py > /dev/null
C:\Full\Path\To\My\Game.exe > nul

여러 프로세스를 처리하지 않는 한,이 해야 작동합니다. Windows 사용자의 경우 생성중인 바로 가기 (시작 메뉴 / 데스크톱)가 될 수 있습니다.


1

내가 사용했던 모듈은 stderr. 따라서이 경우의 해결책은 다음과 같습니다.

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

1

@Alexander Chzhen 솔루션을 기반으로 인쇄를 억제할지 여부를 옵션으로 기능에 적용하는 방법을 여기에 제시합니다.

    import os, sys
    class SuppressPrints:
        #different from Alexander`s answer
        def __init__(self, suppress=True):
            self.suppress = suppress

        def __enter__(self):
            if self.suppress:
                self._original_stdout = sys.stdout
                sys.stdout = open(os.devnull, 'w')

        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.suppress:
                sys.stdout.close()
                sys.stdout = self._original_stdout
    #implementation
    def foo(suppress=True):
        with SuppressPrints(suppress):
            print("It will be printed, or not")

    foo(True)  #it will not be printed
    foo(False) #it will be printed

Alexander의 답변 아래에 내 솔루션을 주석으로 추가 할 수 있기를 바랍니다.하지만 그렇게 할만한 평판이 충분하지 않습니다.


0

간단한 리디렉션을 수행 할 수 있습니다. 이것은 stdout을 엉망으로 만드는 것보다 훨씬 안전 해 보이며 추가 라이브러리를 가져 오지 않습니다.

enable_print  = print
disable_print = lambda *x, **y: None

print = disable_print
function_that_has_print_in_it(1)  # nothing is printed

print = enable_print
function_that_has_print_in_it(2)  # printing works again!

참고 : 이것은 print () 함수를 비활성화하는 데만 작동하며 출력을 생성하는 다른 항목을 호출하는 경우 모든 출력을 비활성화하지 않습니다. 예를 들어 자체 출력을 생성하는 C 라이브러리를 stdout으로 호출하거나 intput ()을 사용하는 경우입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.