it-swarm.com.de

Aufrufe zum Drucken unterdrücken (Python)

Gibt es eine Möglichkeit, eine Funktion vom Aufruf von print abzuhalten?


Ich verwende das Modul pygame.joystick für ein Spiel, an dem ich arbeite.

Ich habe ein pygame.joystick.Joystick-Objekt erstellt und in der aktuellen Schleife des Spiels seine Mitgliedsfunktion get_button aufgerufen, um die Benutzereingaben zu überprüfen. Die Funktion macht alles, was ich brauche, aber das Problem ist, dass sie auch print aufruft, was das Spiel erheblich verlangsamt. 

Kann ich diesen Aufruf an printblockieren?

39
dmlicht

Mit Python können Sie die Standardausgabe (stdout) mit einem beliebigen Dateiobjekt überschreiben. Dies sollte plattformübergreifend funktionieren und auf das Nullgerät schreiben.

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"

Wenn Sie nicht möchten, dass diese eine Funktion gedruckt wird, rufen Sie blockPrint() und enablePrint() auf, wenn Sie fortfahren möchten. Wenn Sie das Drucken von all deaktivieren möchten, starten Sie das Blockieren oben in der Datei.

53
FakeRainBrigand

Basierend auf der @FakeRainBrigand-Lösung schlage ich eine sicherere Lösung vor:

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

Dann kannst du es so benutzen:

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

print("This will be printed as before")

Dies ist viel sicherer, da Sie nicht vergessen können, stdout erneut zu aktivieren, was besonders bei der Behandlung von Ausnahmen wichtig ist.

# This is an example of not-so-good solution
# without 'with' context manager statement.
try:
    disable_prints()
    something_throwing()
    # enable_prints() This wouldn't be enough!
except ValueError:
    handle_error()
finally:
    enable_prints() # That's where it needs to go.

Wenn Sie die finally-Klausel vergessen haben, würde keiner Ihrer print-Aufrufe mehr drucken. Mit der with-Anweisung kann das nicht passieren.

Die Verwendung von sys.stdout = None ist nicht sicher, da jemand Methoden wie sys.stdout.write () aufrufen kann.

39

Nein, das ist nicht der Fall, insbesondere, dass die Mehrheit von PyGame in C geschrieben ist.

Wenn diese Funktion print aufruft, ist es der PyGame-Fehler, und Sie sollten es einfach melden.

4
Cat Plus Plus

Ich hatte das gleiche Problem, und ich kam nicht zu einer anderen Lösung, sondern um die Ausgabe des Programms umzuleiten (ich weiß nicht genau, ob das Spammen auf stdout oder stderr geschieht) an /dev/null Nirvana. 

Es ist zwar Open Source, aber ich war nicht leidenschaftlich genug, um mich mit den pygame-Quellen und dem Build-Prozess zu beschäftigen, um den Debug-Spam irgendwie zu stoppen. 

EDIT: 

Das pygame.joystick-Modul hat Aufrufe von printf in allen Funktionen, die die tatsächlichen Werte an Python zurückgeben:

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

Leider müssten Sie diese auskommentieren und das Ganze neu kompilieren. Vielleicht würde der mitgelieferte setup.py das einfacher machen, als ich dachte. Sie könnten dies versuchen ...

2
moooeeeep

Wenn Sie Druckaufrufe blockieren möchten, die von einer bestimmten Funktion ausgeführt werden, gibt es eine aufgeräumte Lösung, die Dekorateure verwendet. Definieren Sie den folgenden Dekorateur:

# 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

Platzieren Sie einfach @blockPrinting vor einer Funktion. Zum Beispiel:

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

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

Das Modul, das ich verwendet habe, wurde in stderr gedruckt. Die Lösung in diesem Fall wäre also:

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

Wie @Alexander Chzhen vorschlug, wäre die Verwendung eines Kontextmanagers sicherer als das Aufrufen eines Paares von Zustandsänderungsfunktionen.

Sie müssen den Kontext-Manager jedoch nicht erneut implementieren - er ist bereits in der Standardbibliothek enthalten. Sie können stdout (das von print verwendete Dateiobjekt) mit contextlib.redirect_stdout und auch stderr mit contextlib.redirect_stderr umleiten.

import os
import contextlib

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

Ein völlig anderer Ansatz wäre eine Umleitung in der Befehlszeile. Unter Windows bedeutet dies ein Batch-Skript. Unter Linux bash. 

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

Wenn Sie nicht mit mehreren Prozessen zu tun haben, funktioniert dies sollte. Für Windows-Benutzer können dies die Verknüpfungen sein, die Sie erstellen (Startmenü/Desktop).

1
FakeRainBrigand

Basierend auf der @Alexander Chzhen-Lösung präsentiere ich hier die Möglichkeit, sie auf eine Funktion anzuwenden, mit der Option, das Drucken zu unterdrücken oder nicht.

    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

Ich hoffe, ich kann meine Lösung unter der Antwort von Alexander als Kommentar hinzufügen, aber ich habe nicht genug (50) Ruf, um dies zu tun.

0
Quân Hoàng