Подавить сообщение stdout из библиотеки C/C++

Я пытаюсь подавить сообщение, которое выводится на стандартный вывод библиотекой, реализованной на C.

Мой конкретный вариант использования — OpenCV, поэтому я буду использовать его для MCVE ниже. Функция AssessmentChessboardSharpness имеет распечатку, когда размер сетки слишком мал (что происходит здесь ). Я сделал пиар, чтобы это исправить, но пока мне хотелось бы скрыть это сообщение. Например:

import cv2
import numpy as np

img = np.zeros((512, 640), dtype='uint8')
corners = []
for i in range(10):
    for j in range(8):
        corner = (30 + 3 * j, 70 + 3 * i)
        if i and j:
            corners.append(corner)
        if (i % 2) ^ (j % 2):
            img[corner[0]:corner[0] + 3, corner[1]:corner[1] + 3] = 255
corners = np.array(corners)
>>> cv2.estimateChessboardSharpness(img, (9, 7), corners)
calcEdgeSharpness: checkerboard too small for calculation.
((9999.0, 9999.0, 9999.0, 9999.0), None)

Строка выглядит простой std::cout << ..., поэтому я попробовал все следующее:

from contextlib import redirect_stdout
from os imoprt devnull
import sys

with redirect_stdout(None):
    cv2.estimateChessboardSharpness(img, (9, 7), corners)

with open(devnull, "w") as null, redirect_stdout(null):
    cv2.estimateChessboardSharpness(img, (9, 7), corners)

sys.stdout = open(devnull, "w")
cv2.estimateChessboardSharpness(img, (9, 7), corners)

Я даже попробовал redirect_stderr вместо redirect_stdout на всякий случай. Я также пробовал установить OPENCV_LOG_LEVEL=SILENT в bash и os.environ["OPENCV_LOG_LEVEL"] = "SILENT" в python перед импортом cv2, но не ожидал, что в этом случае стандартный вывод будет объединен с журналированием.

Во всех случаях сообщение печатается. Как мне остановить это?

Вы перенаправляете объект файла Python sys.stdout, а не базовый C FILE *stdout или файловый дескриптор ниже него. Код, отличный от Python, не будет использовать файловый объект Python. os.dup2 будет работать, но это некрасиво.

Useless 14.07.2024 23:03

@Бесполезный. Уродливо - это нормально. Как ты делаешь это?

Mad Physicist 14.07.2024 23:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предполагая UNIX-подобную платформу (в противном случае вы получите OSError)

Вы можете сохранить базовый fd с помощью

backup = os.dup(sys.stdout.fileno())

укажите другой файл (например, different) с помощью

os.dup2(different.fileno(), sys.stdout.fileno())

и возобновите нормальное обслуживание с помощью

os.dup2(backup, sys.stdout.fileno())

Обратите внимание, что это будет вести себя совсем нехорошо, если файл, на который вы перенаправляете, также используется для буферизованного вывода (т. е. у вас есть запись в different, смешанная с записью в библиотеку C++, в std::cout, которая использует different.fileno()...)

Выберу, если получится. Это совсем не уродливо. Фактически, это, по сути, один контекстный менеджер, чтобы быть довольно простым.

Mad Physicist 15.07.2024 00:29

Тот факт, что он зависит от платформы и требует детализации двух уровней абстракции, является уродливым. По крайней мере, это не так уж и сложно.

Useless 15.07.2024 00:32

Справедливо. Кроме того, кстати, согласно документации, это должно работать в Windows. Я давно не видел машины с Windows, так что мне все равно :)

Mad Physicist 15.07.2024 01:10

Стоит ли мне закрывать backup после завершения? Моя интуиция говорит да, но я все еще не на 100% понимаю, что такое Fileno на самом деле.

Mad Physicist 15.07.2024 08:58

Это просто еще одна ссылка на стандартный вывод на практике. На самом деле вам не нужно его закрывать, если только у вас не закончились файловые дескрипторы, но аккуратность является достаточно веской причиной.

Useless 17.07.2024 00:13

Идеально: gitlab.com/mad Physicscist/haggis/-/blob/master/src/haggis/…

Mad Physicist 17.07.2024 00:47

Очень хорошая реализация!

Useless 18.07.2024 09:56

Другие вопросы по теме