python - যবহ - পাইথন প্রোগ্রামিং বাংলা বই pdf




পাইথন ফাংশন দ্বারা চালিত এক্সিকিউটেবলের টার্মিনাল আউটপুটটি কীভাবে একটি সাধারণ উপায়ে নীরব করা যায়? (2)

এক্সিকিউটেবলের দ্বারা চালিত ফাংশন দ্বারা উত্পাদিত সমস্ত টার্মিনাল আউটপুটকে আমি দমন করতে চাই।

আমি একটি প্রসঙ্গ পরিচালক ব্যবহার করে পাইথন ফাংশনটির আউটপুট দমন করার চেষ্টা করেছি যা প্রতিটি সময় যখন ফাংশন বলা হয় তখন স্টাডআউট এবং স্ট্ডারকে অস্থায়ীভাবে সংজ্ঞা দেয়। এটি ফাংশনে print কল দ্বারা উত্পাদিত টার্মিনাল আউটপুটকে দমন করে, তবে ফাংশন টার্মিনাল আউটপুট উত্পাদনকারী এক্সিকিউটেবলকে কল করলে এটি কাজ করবে বলে মনে হয় না।

সুতরাং, পাইথন ফাংশন দ্বারা ডাকা এক্সিকিউটেবলের আউটপুট কীভাবে দমন করা যায়?

আমার কোডটি নীচে। আমি উদাহরণস্বরূপ একটি ফাংশন অন্তর্ভুক্ত করেছি যা আমি যে ধরণের টার্মিনাল আউটপুটটি দমন করতে চাই তা চিত্রিত করার চেষ্টা করার জন্য ls কল করে (যদিও আমি যে ফাংশনটি নিয়ে কাজ করছি তার চেয়ে আলাদা)।

#!/usr/bin/env python

import os
import subprocess
import sys

def main():

    print("hello")

    with silence():
        print("there")

    print("world")

    with silence():
        engage_command(command = "ls")

class silence(object):

    def __init__(
        self,
        stdout = None,
        stderr = None
        ):
        if stdout == None and stderr == None:
            devnull = open(os.devnull, "w")
            stdout = devnull
            stderr = devnull
        self._stdout = stdout or sys.stdout
        self._stderr = stderr or sys.stderr

    def __enter__(
        self
        ):
        self.old_stdout = sys.stdout
        self.old_stderr = sys.stderr
        self.old_stdout.flush()
        self.old_stderr.flush()
        sys.stdout = self._stdout
        sys.stderr = self._stderr

    def __exit__(
        self,
        exc_type,
        exc_value,
        traceback
        ):
        self._stdout.flush()
        self._stderr.flush()
        sys.stdout = self.old_stdout
        sys.stderr = self.old_stderr

def engage_command(
    command = None
    ):
    process = subprocess.Popen(
        [command],
        shell      = True,
        executable = "/bin/bash")
    process.wait()
    output, errors = process.communicate()
    return output

if __name__ == "__main__":
    main()

আমার বিশেষ ক্ষেত্রে, আমি নিম্নলিখিত ফাংশনটি চালানোর চেষ্টা করছি (উপরে ls ফাংশনের পরিবর্তে):

with propyte.silence():
    stream = pyaudio.PyAudio().open(
        format   = pyaudio.PyAudio().get_format_from_width(1),
        channels = 1, 
        rate     = bitrate, 
        output   = True
    )

রান করার সময় এটি নিম্নলিখিতগুলির মতো আউটপুট উত্পন্ন করে:

ALSA lib pcm_dsnoop.c:606:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock

আমি যে আউটপুট দমন করতে চান।

সম্পাদনা: @ মাথিয়াস দ্বারা সরবরাহিত একটি সমাধান পরীক্ষা করে

#!/usr/bin/env python

import contextlib
import os
import subprocess
import sys

def main():

    print("hello")

    with silence():
        print("there")

    print("world")

    with silence():
        engage_command(command = "ls")

@contextlib.contextmanager
def silence():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stderr = os.dup(2)
    sys.stderr.flush()
    os.dup2(devnull, 2)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stderr, 2)
        os.close(old_stderr)

def engage_command(
    command = None
    ):
    process = subprocess.Popen(
        [command],
        shell      = True,
        executable = "/bin/bash")
    process.wait()
    output, errors = process.communicate()
    return output

if __name__ == "__main__":
    main()

আমি print বা এলএস থেকে টার্মিনাল আউটপুট দমন করতে সফল হইনি এবং কেন তা নিশ্চিত তা আমি নিশ্চিত নই।


আপনি পাইউডিও থেকে sounddevice মডিউলে স্যুইচ করতে পারেন, যা ইতিমধ্যে টার্মিনাল আউটপুট স্তব্ধ করে রাখার যত্ন নিয়েছে ( #12 )। এটি এখানে এটি করা হয় (সিএফএফআই ব্যবহার করে):

from cffi import FFI
import os

ffi = FFI()
ffi.cdef("""
/* from stdio.h */
FILE* fopen(const char* path, const char* mode);
int fclose(FILE* fp);
FILE* stderr;  /* GNU C library */
FILE* __stderrp;  /* Mac OS X */
""")
try:
    stdio = ffi.dlopen(None)
    devnull = stdio.fopen(os.devnull.encode(), b'w')
except OSError:
    return
try:
    stdio.stderr = devnull
except KeyError:
    try:
        stdio.__stderrp = devnull
    except KeyError:
        stdio.fclose(devnull)

আপনি যদি খাঁটি পাইথন সমাধান চান তবে আপনি এই প্রসঙ্গ পরিচালকটি চেষ্টা করতে পারেন:

import contextlib
import os
import sys

@contextlib.contextmanager
def ignore_stderr():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stderr = os.dup(2)
    sys.stderr.flush()
    os.dup2(devnull, 2)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stderr, 2)
        os.close(old_stderr)

বিষয়টি সম্পর্কে এটি একটি খুব সহায়ক ব্লগ পোস্ট: http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/

হালনাগাদ:

উপরের কনটেক্সট ম্যানেজারটি স্ট্যান্ডার্ড ত্রুটি আউটপুট ( stderr ) stderr , যা মূল প্রশ্নে উল্লিখিত পোর্টএউডিওর বিরক্তিকর বার্তার জন্য ব্যবহৃত হয়। আপনার আপডেট হওয়া প্রশ্নের মতো স্ট্যান্ডার্ড আউটপুট ( stdout ) থেকে মুক্তি পেতে আপনাকে sys.stderr সাথে sys.stdout এবং ফাইল বর্ণনাকারী 2 সাথে 1 নম্বর দিয়ে প্রতিস্থাপন করতে হবে:

@contextlib.contextmanager
def ignore_stdout():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stdout = os.dup(1)
    sys.stdout.flush()
    os.dup2(devnull, 1)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stdout, 1)
        os.close(old_stdout)

বিশেষত ALSA ত্রুটির জন্য, আপনি এই প্রশ্নের উদাহরণ হিসাবে বর্ণিত হিসাবে ALSA এর snd_lib_error_set_handler ফাংশনটি ব্যবহার করতে পারেন।

আমার একটি প্রকল্পের জন্য, আমি mute_alsa নামে একটি মডিউল তৈরি mute_alsa , যা দেখতে mute_alsa মতো দেখাচ্ছে:

import ctypes

ERROR_HANDLER_FUNC = ctypes.CFUNCTYPE(None, ctypes.c_char_p, ctypes.c_int,
                                      ctypes.c_char_p, ctypes.c_int,
                                      ctypes.c_char_p)


def py_error_handler(filename, line, function, err, fmt):
    pass

c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)

try:
    asound = ctypes.cdll.LoadLibrary('libasound.so.2')
    asound.snd_lib_error_set_handler(c_error_handler)
except OSError:
    pass

এবং আপনি কেবল নিজের কোডটিতে নিম্নলিখিতটি রেখে এটি ব্যবহার করেন:

import mute_alsa

আরও সাধারণ অর্থে, আপনি কেবল প্রাসঙ্গিক ফাইল ডেস্ক্রিপ্টার বন্ধ করে stderr মুদ্রণ থেকে কোনও কিছুই রোধ করতে পারেন। উদাহরণস্বরূপ, আমরা যদি অস্তিত্বহীন এমন কোনও ফাইলকে rm করার চেষ্টা করি তবে আমরা stderr মুদ্রিত একটি ত্রুটি বার্তা পাই:

>>> import sys
>>> import os
>>> os.system('rm /doesnotexist')
rm: cannot remove ‘/doesnotexist’: Is a directory
256

যদি আমরা stderr ফাইল বিবরণী বন্ধ করি:

>>> os.close(sys.stderr.fileno())

আমরা আর কোনও ত্রুটি বার্তা দেখতে পাচ্ছি না:

>>> os.system('rm /doesnotexist')

এই পদ্ধতির নেতিবাচক দিকটি হ'ল এটি স্ট্যান্ডারের কাছে সমস্ত বার্তা stderr যার অর্থ আপনি বৈধ ত্রুটি বার্তাগুলি আর দেখতে পাবেন না। এটি আশ্চর্যজনক ব্যর্থতা মোডের দিকে নিয়ে যেতে পারে (কোনও ত্রুটি মুদ্রণ না করেই প্রোগ্রামটি বেরিয়ে এসেছে!)।





silent