अजगर में "कुछ भी नहीं" के लिए stdout पुनर्निर्देशित करना


128

मेरे पास एक बड़ी परियोजना है जिसमें पर्याप्त बड़ी संख्या में मॉड्यूल हैं, प्रत्येक मानक उत्पादन के लिए कुछ छपाई करता है। अब जैसे-जैसे यह परियोजना आकार में बढ़ी है, बड़ी संख्या में हैं। की printएसटीडी बाहर जो काफी धीमी कार्यक्रम बना दिया है पर बहुत कुछ मुद्रण बयान।

इसलिए, मैं अब रनटाइम पर फैसला करना चाहता हूं कि क्या स्टडआउट को कुछ प्रिंट करना है या नहीं। मैं मॉड्यूल में बदलाव नहीं कर सकता क्योंकि उनमें से बहुत सारे हैं। (मुझे पता है कि मैं स्टडआउट को एक फ़ाइल पर पुनर्निर्देशित कर सकता हूं लेकिन यहां तक ​​कि यह काफी धीमा है।)

तो मेरा सवाल यह है कि मैं स्टडआउट को कुछ भी नहीं करने के लिए कैसे करूँ अर्थात मैं कैसे 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.

वर्तमान में मेरे पास एकमात्र विचार एक वर्ग बनाना है जिसमें एक लेखन विधि है (जो कुछ भी नहीं करता है) और इस वर्ग के एक उदाहरण के लिए स्टडआउट को पुनर्निर्देशित करता है।

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

dp = DontPrint()
sys.stdout = dp

क्या इसके लिए अजगर में एक इनबिल्ट मैकेनिज्म है? या इससे कुछ बेहतर है?



1
मैंने सिर्फ एक अजीबोगरीब चीज खोजी है। Sys.stdout को किसी में बदलना वास्तव में मेरे कार्यक्रम में काम करता है, हालांकि मुझे यकीन नहीं है कि क्यों। मैं वास्तव में अजीब समस्याओं के साथ os.devnull को पुनर्निर्देशित कर रहा था इसलिए मैंने सिर्फ किसी का उपयोग करने की कोशिश नहीं की, और यह काम करता है। मेरे पास कुछ करने के लिए एक Django इकाई परीक्षण में यह कर सकता है, लेकिन मुझे यकीन नहीं है।
तेईकिन

जवाबों:


233

क्रॉस-प्लेटफॉर्म:

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

विंडोज पर:

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

लिनक्स पर:

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

फिर आप इसे कैसे रद्द करेंगे? क्या आपके द्वारा किए जाने के बाद प्रिंट स्टेटमेंट को वापस चालू करने का कोई तरीका है?
jj172

4
ज़रूर, बस मूल के संदर्भ को सहेजें sys.stdoutऔर इसे बाद में सेट करें। उदाहरण के लिए old_stdout = sys.stdoutकिसी भी अन्य कोड से पहले, तब sys.stdout = old_stdoutजब आप कर रहे हों।
एंड्रयू क्लार्क

1
ध्यान दें: यह एक फ़ाइल वर्णनकर्ता स्तर यानी पर रीडायरेक्ट नहीं करता है, यह बाहरी बच्चे प्रक्रियाओं के उत्पादन, सी एक्सटेंशन से उत्पादन है कि सी के लिए प्रिंट सीधे stdout अनुप्रेषित करने में विफल हो सकता, os.write(1, b'abc\n')। आपको os.dup2()फ़ाइल डिस्क्रिप्टर स्तर पर रीडायरेक्ट करने की आवश्यकता है, देखेंstdout_redirected()
jfs

4
नोट sys.__stdout__पुनर्निर्देशन रद्द करने के लिए है। तो आप बस करते हैं sys.stdout = sys.__stdout__और बैकअप स्टोर करने की आवश्यकता नहीं है।
कॉन्स्टेंटिन सेकेरेश

28

ऐसा करने का एक अच्छा तरीका यह है कि आप एक छोटे से संदर्भ प्रोसेसर का निर्माण करें, जिसमें आप अपने प्रिंट को लपेटते हैं। आप तब उपयोग करते हैं, जो कि 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+:

पायथॉन 3.4 में इस बिल्ट-इन की तरह एक संदर्भ प्रोसेसर है, इसलिए आप इस तरह से केवल संदर्भ सूची का उपयोग कर सकते हैं:

import contextlib

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

print("this will print")

इस कोड को चलाने से केवल आउटपुट की दूसरी लाइन प्रिंट होती है, पहली नहीं:

$ python test.py
this will print

यह क्रॉस-प्लेटफ़ॉर्म (विंडोज + लिनक्स + मैक ओएसएक्स) पर काम करता है, और अन्य जवाबों की तुलना में क्लीनर है।


@celticminstrel आप पूरी तरह से सही हैं, मुझे सही करने के लिए धन्यवाद। मैंने sys.stdout को बाद में रीसेट करने के लिए कोड अपडेट किया है।
एमिल स्टेंस्ट्रम

यह कुछ त्रुटि जाँच याद आ रही है, लेकिन महान विचार
मैड फिजिसिस्ट

जोड़ा कोड यह दिखाने के लिए कि यह पायथन 3 में भी कैसे काम करता है।
एमिल स्टेनस्ट्रॉम

15

यदि आप अजगर 3.4 या उच्चतर में हैं, तो मानक पुस्तकालय का उपयोग करके एक सरल और सुरक्षित समाधान है:

import contextlib

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

3
with contextlib.redirect_stdout(None)के रूप में अच्छी तरह से काम करता है
क्रिस Cogdon

@ क्रिसहोगडन बहुत अच्छा संकेत है, मैंने उसके अनुसार उत्तर संपादित किया।
iFreilicht

1
काम नहीं करता है अगर आप pprint पुस्तकालय का उपयोग कर रहे हैं। AttributeError: 'NoneType' object has no attribute 'write'
Speeeddy

@Speeeddy क्या आपको यह त्रुटि अजगर 2 के साथ मिली? आप एक डमी writeविधि के साथ एक वर्ग बना सकते हैं जो कुछ भी नहीं करता है। नीचे मेरा जवाब देखें।
dizcza

8

(कम से कम मेरे सिस्टम पर) ऐसा प्रतीत होता है कि 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

4
बस रिकार्ड के लिए, अगली बार जब आप समय कुछ करना चाहते हैं, बस का उपयोग timeit
एंटोनी पैलिस्सी

6

यदि आप एक यूनिक्स वातावरण (लिनक्स में शामिल) में हैं, तो आप आउटपुट को इनडायरेक्ट कर सकते हैं /dev/null:

python myprogram.py > /dev/null

और विंडोज के लिए:

python myprogram.py > nul

2
इसका बेहतर समाधान है जो सभी प्लेटफार्मों पर काम करेगा।
पुष्पक डगड़े

2
@Guanidene, शायद, लेकिन अगर वह अपने कार्यक्रम का उपयोग करने वाला एकमात्र व्यक्ति है, तो वह पर्यावरण की बहुत गारंटी दे सकता है।
निक रैडफोर्ड

nul = myfunc() ?
Hicsy

2

इस बारे में कैसा है:

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()

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

आप मानक त्रुटि उत्पादन को छिपाने के लिए चाहते हैं, तो आयात redirect_stderrसे contextlibऔर एक लाइन कह जोड़ने stack.enter_context(redirect_stderr(null_stream))

मुख्य नकारात्मक पक्ष यह है कि यह केवल पायथन 3.4 और बाद के संस्करणों में काम करता है।



1

आपकी कक्षा ठीक काम करेगी ( write()विधि नाम के अपवाद के साथ - इसे कॉल करने की आवश्यकता है write(), लोअरकेस)। बस सुनिश्चित करें कि आप sys.stdoutकिसी अन्य चर की एक प्रति सहेज लें ।

यदि आप एक * NIX पर हैं, तो आप कर सकते हैं sys.stdout = open('/dev/null'), लेकिन यह आपकी अपनी कक्षा को रोल करने की तुलना में कम पोर्टेबल है।



0

आप यह कोशिश क्यों नहीं करते?

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

क्योंकि ए) यह भी काम नहीं कर सकता है, और बी) यदि ऐसा होता है, तो आपको आउटपुट को दबाने के बजाय एक त्रुटि मिलेगी।
मैड फिजिसिस्ट

0
sys.stdout = None

यह print()मामले के लिए ठीक है। लेकिन अगर आप sys.stdout के किसी भी तरीके को कहते हैं, तो यह एक त्रुटि का कारण बन सकता है sys.stdout.write()

डॉक्स में एक नोट है :

कुछ शर्तों के तहत, स्टैडआउट और स्टैडर के साथ-साथ मूल मान स्टड , स्टडआउट और स्टेडर कोई नहीं हो सकता है। यह आमतौर पर विंडोज जीयूआई ऐप के लिए मामला है जो कंसोल से जुड़ा नहीं है और पायथन ऐप की शुरुआत अजगर से हुई है।


"ठीक है" और "जिस क्षण आप प्रिंट करने का प्रयास करते हैं वह एक त्रुटि नहीं होगी" इस मामले में बहुत अलग चीजें हैं।
मैड फिजिसिस्ट

1
आप सही हे। आप किसी भी विधि को इस तरह से नहीं बुला सकते हैं कि sys.stdout = Nullकुछ मामलों में यह खतरनाक हो सकता है।
अलेक्जेंडर चेजन

इस सटीक मामले में यह खतरनाक माना जाता है। ओपी विशेष रूप से उस त्रुटि को संबोधित करता है जो उसे करने से मिलती है।
मैड फिजिसिस्ट

0

IFreilicht के उत्तर के लिए पूरक - यह अजगर 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!")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.