कॉल को प्रिंट करने के लिए कैसे ब्लॉक करें?


81

क्या किसी फ़ंक्शन को कॉल करने से रोकने का कोई तरीका है print?


मैं जिस pygame.joystickगेम पर काम कर रहा हूं उसके लिए मैं मॉड्यूल का उपयोग कर रहा हूं।

मैंने एक pygame.joystick.Joystickऑब्जेक्ट बनाया और गेम के वास्तविक लूप में get_buttonउपयोगकर्ता इनपुट के लिए जाँच करने के लिए इसके सदस्य फ़ंक्शन को कॉल करें । फ़ंक्शन वह सब कुछ करता है जो मुझे करने की आवश्यकता है, लेकिन समस्या यह है कि यह कॉल भी करता है print, जो खेल को काफी धीमा कर देता है।

क्या मैं इस कॉल को ब्लॉक कर सकता हूं print?

जवाबों:


108

पायथन आपको किसी भी फ़ाइल ऑब्जेक्ट के साथ मानक आउटपुट (stdout) को अधिलेखित करने देता है। यह क्रॉस प्लेटफॉर्म पर काम करना चाहिए और नल डिवाइस को लिखना चाहिए।

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 इसे पुनर्स्थापित नहीं करता है
जॉनी 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")

यह बहुत सुरक्षित है क्योंकि आप स्टैडआउट को फिर से सक्षम करने के लिए नहीं भूल सकते हैं, जो अपवादों को संभालते समय विशेष रूप से महत्वपूर्ण है।

के बिना 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
बहुत अच्छा समाधान! मैंने बस एक ही बात लिखी और फिर पाया कि आप पहले से ही इस तरह से जवाब दे चुके हैं: डी मैं इस बारे में थोड़ी जानकारी जोड़ूंगा कि यह करने का एक बेहतर तरीका क्यों है।
iFreilicht

Noobie यहाँ सवाल: क्या यह () वर्ग से बाहर निकलने के बाद devnull को बंद करने के लिए महत्वपूर्ण होगा?
jlsecrest

@Wadsworth, मुझे इसका उत्तर नहीं पता है। मुझे लगता है कि देवनुल के गुणों को इसे ठीक से बंद करने की आवश्यकता नहीं है। लेकिन अफवाहों का कहना है कि आपको संसाधनों को जारी करने के लिए हमेशा खुले हैंडलर को बंद करना चाहिए। CPython जैसा कि मुझे पता है कि जहां तक ​​कचरा संग्रहकर्ता को मिलता है, अपने आप को devnull को बंद कर देना चाहिए।
अलेक्जेंडर चेजन

2
ResourceWarning: unclosed file <_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>इस कोड का उपयोग करते समय मुझे मिल रहा था , इसे sys.stdout = ओपन के बजाय कोई नहीं सुलझाया (os.devnull, 'w')
WellDone2094

@ WellDone2094, धन्यवाद। मैंने sys.stdout.close()निकास विधि में जोड़ा है। यह मदद करनी चाहिए। ध्यान दें कि sys.stdout = Noneकोई त्रुटि हो सकती है, क्योंकि कोई व्यक्ति stdout के तरीकों को कॉल कर सकता है sys.stdout.write()
अलेक्जेंडर चेजन

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 में लिखा गया है।

लेकिन अगर यह फ़ंक्शन प्रिंट को कॉल करता है, तो यह PyGame Bug है, और आपको इसे रिपोर्ट करना चाहिए।


2

मेरे पास एक ही समस्या है, और मैं दूसरे समाधान के लिए नहीं आया था, लेकिन कार्यक्रम के आउटपुट को पुनर्निर्देशित करने के लिए (मुझे ठीक से नहीं पता है कि /dev/nullनिर्वाण stdout या stderr पर होता है) निर्वाण के लिए।

वास्तव में, यह खुला स्रोत है, लेकिन मैं pygameसूत्रों में गोता लगाने के लिए पर्याप्त भावुक नहीं था - और निर्माण प्रक्रिया - किसी तरह डिबग स्पैम को रोकने के लिए।

संपादित करें:

pygame.joystickमॉड्यूल के लिए कॉल किया है printfसभी कार्यों कि अजगर को वास्तविक मान में:

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

दुर्भाग्य से आपको इन पर टिप्पणी करनी होगी और पूरी बात को फिर से लिखना होगा। शायद यह प्रदान करने setup.pyसे मुझे लगता है कि यह आसान हो जाएगा। आप यह कोशिश कर सकते हैं ...


2

एक पूरी तरह से अलग दृष्टिकोण कमांड लाइन पर पुनर्निर्देशित किया जाएगा। यदि आप विंडोज पर हैं, तो इसका मतलब एक बैच स्क्रिप्ट है। लिनक्स पर, बैश।

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

जब तक आप कई प्रक्रियाओं के साथ काम नहीं कर रहे हैं, यह काम करना चाहिए । विंडोज उपयोगकर्ताओं के लिए यह आपके द्वारा बनाए जा रहे शॉर्टकट (प्रारंभ मेनू / डेस्कटॉप) हो सकते हैं।


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

मुझे आशा है कि मैं एक टिप्पणी के रूप में अलेक्जेंडर के जवाब के नीचे अपना समाधान जोड़ सकता हूं, लेकिन मेरे पास ऐसा करने के लिए पर्याप्त (50) प्रतिष्ठा नहीं है।


0

आप एक सरल पुनर्निर्देशन कर सकते हैं, यह स्टडआउट के साथ खिलवाड़ करने की तुलना में बहुत अधिक सुरक्षित लगता है, और किसी भी अतिरिक्त पुस्तकालयों में नहीं खींचता है।

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!

नोट: यह केवल प्रिंट () फ़ंक्शन को अक्षम करने के लिए काम करता है, और यदि आप किसी अन्य चीज़ को कॉल कर रहे हैं जो आउटपुट का उत्पादन कर रहा है, तो सभी आउटपुट को अक्षम नहीं करेगा। उदाहरण के लिए, यदि आप एक सी लाइब्रेरी का निर्माण कर रहे थे, जो स्टडआउट करने के लिए स्वयं का उत्पादन कर रही थी, या यदि आप इंटपुट () का उपयोग कर रहे थे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.