অজগরের স্টাডাউটকে "কিছুই না" তে পুনর্নির্দেশ করা হচ্ছে


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
আমি সবেমাত্র একটি অদ্ভুত জিনিস আবিষ্কার করেছি। সিস্টেস্টডাউটকে কারও মধ্যে রূপান্তর করা আসলে আমার প্রোগ্রামে কাজ করে না, যদিও আমি নিশ্চিত তা না। ওস.দেবনুলকে পুনঃনির্দেশিত করার সাথে সাথে এনকোডিংয়ের সাথে আমার সত্যিই অদ্ভুত সমস্যা ছিল তাই আমি কেবল কোনওটিই ব্যবহার করার চেষ্টা করিনি এবং এটি কার্যকর। জ্যাঙ্গো ইউনিট পরীক্ষায় এটি করার সাথে আমার কিছু করার থাকতে পারে তবে আমি নিশ্চিত নই।
তেখিন

উত্তর:


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
দ্রষ্টব্য: এটি কোনও ফাইল বর্ণনাকারী স্তরে পুনর্নির্দেশ করে না অর্থাত্, এটি বাহ্যিক শিশু প্রক্রিয়াগুলির আউটপুট পুনর্নির্দেশ করতে ব্যর্থ হতে পারে, সি এক্সটেনশান থেকে সি স্টাডআউটে প্রিন্ট করা আউটপুট সরাসরি স্ট্যান্ডআউট os.write(1, b'abc\n'),। আপনি প্রয়োজন os.dup2(), ফাইল বর্ণনাকারী পর্যায়ে পুনর্নির্দেশ করতে দেখতেstdout_redirected()
JFS

4
মনে রাখবেন যে sys.__stdout__কোনও পুনঃনির্দেশ বাতিল করার জন্য রয়েছে । সুতরাং আপনি ঠিক করছেন sys.stdout = sys.__stdout__এবং ব্যাকআপ সংরক্ষণ করার প্রয়োজন নেই।
কনস্ট্যান্টিন সেকেরেশ

28

এটি করার একটি দুর্দান্ত উপায় হ'ল একটি ছোট প্রসঙ্গ প্রসেসর তৈরি করা যাতে আপনি নিজের প্রিন্টগুলি মুড়ে রাখেন You আপনি কেবলমাত্র 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")

পাইথন ৩.৪++:

পাইথন ৩.৪-তে একটি বিল্ট-ইন-এর মতো একটি প্রসঙ্গ প্রসেসর রয়েছে, সুতরাং আপনি কেবল প্রাসঙ্গিকটি এই জাতীয় ব্যবহার করতে পারেন:

import contextlib

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

print("this will print")

এই কোডটি চালানো কেবল প্রথম নয়, আউটপুটটির দ্বিতীয় লাইনটি মুদ্রণ করে:

$ python test.py
this will print

এটি ক্রস-প্ল্যাটফর্ম (উইন্ডোজ + লিনাক্স + ম্যাক ওএসএক্স) কাজ করে এবং অন্য উত্তরগুলির চেয়ে পরিষ্কার।


@ ব্যতীত আপনি পুরোপুরি ঠিক বলেছেন, আমাকে সংশোধন করার জন্য ধন্যবাদ। Sys.stdout পরে পুনরায় সেট করতে আমি কোড আপডেট করেছি updated
এমিল স্টেনস্ট্রোম

এটিতে কিছু ত্রুটি পরীক্ষা করা অনুপস্থিত, তবে দুর্দান্ত ধারণা
ম্যাড ফিজিকালিস্ট

পাইথন 3 এ এটি কীভাবে কাজ করে তা দেখানোর জন্য কোড যুক্ত করা হয়েছে।
এমিল স্টেনস্ট্রোম

15

যদি আপনি পাইথন ৩.৪ বা তার বেশি হয় তবে স্ট্যান্ডার্ড লাইব্রেরি ব্যবহার করে একটি সহজ এবং নিরাপদ সমাধান রয়েছে:

import contextlib

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

3
with contextlib.redirect_stdout(None)পাশাপাশি কাজ করে
ক্রিস কগডন

@ ক্রিসকোগডন খুব ভাল ইঙ্গিত, আমি সেই অনুসারে উত্তরটি সম্পাদনা করেছি।
iFreilicht

1
আপনি যদি প্রিন্ট লাইব্রেরি ব্যবহার করেন তবে কাজ করে না। AttributeError: 'NoneType' object has no attribute 'write'
স্পিডি

@ স্পিডি অজগর 2 দিয়ে এই ত্রুটিটি পেয়েছেন? আপনি একটি ডামি writeপদ্ধতি সহ এমন একটি শ্রেণি তৈরি করতে পারেন যা কিছুই করে না। আমার উত্তর নীচে দেখুন।
dizcza

8

(কমপক্ষে আমার সিস্টেমে) এটি উপস্থিত হয় যে os.devnull এ লেখার জন্য একটি দন্টপ্রিন্ট ক্লাসে লেখার চেয়ে প্রায় 5x দ্রুত

#!/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
কেবল রেকর্ডের জন্য, পরের বার আপনি যখন কিছু সময় চান, কেবল সময়সীমাটি
এন্টোইন পেলিস

6

আপনি যদি ইউনিক্স পরিবেশে থাকেন (লিনাক্স অন্তর্ভুক্ত), আপনি আউটপুটটিকে এখানে পুনর্নির্দেশ করতে পারেন /dev/null:

python myprogram.py > /dev/null

এবং উইন্ডোজ জন্য:

python myprogram.py > nul

2
সমস্ত প্ল্যাটফর্মগুলিতে কাজ করে এমন কোনও সমাধান করা ভাল।
পুষ্প দাগাদে

2
@ গুয়ানিডেন, সম্ভবত, তবে তিনি যদি কেবল তাঁর প্রোগ্রামটি ব্যবহার করেন তবে তিনি পরিবেশের গ্যারান্টি অনেকটা দিতে পারেন।
নিক র‌্যাডফোর্ড

nul = myfunc() ?
হিকসি

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

এটি কেবলমাত্র পাইথন ৩.৪ এবং পরবর্তী সংস্করণগুলিতে কাজ করে তার মূল ক্ষতি side



1

আপনার ক্লাসটি ঠিক সূক্ষ্মভাবে কাজ করবে ( write()পদ্ধতির নাম বাদে - এটি write()ছোট হাতের অক্ষরের প্রয়োজন)। কেবলমাত্র নিশ্চিত করুন যে আপনি sys.stdoutঅন্য একটি চলক মধ্যে একটি অনুলিপি সংরক্ষণ করেছেন ।

আপনি যদি একটি * এনআইএক্স থাকেন তবে আপনি এটি করতে পারেন 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এটি কিছু ক্ষেত্রে এটি বিপজ্জনক হতে পারে।
আলেকজান্ডার চেজেন

এই সঠিক ক্ষেত্রে এটি বিপজ্জনক হিসাবে পরিচিত। ওপি বিশেষত এটি করতে গিয়ে যে ত্রুটিটি পেয়েছে তার সমাধান করে।
ম্যাড পদার্থবিদ 18

0

আইফ্রেইলিচের উত্তরের পরিপূরক - এটি অজগর 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!")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.