Как подавить конкретное предупреждение из скрипта Python? - PullRequest
2 голосов
/ 26 июня 2019

Я получаю конкретное предупреждение, которое могу надежно игнорировать.Это предупреждение, вероятно, будет в конечном итоге исправлено, и моя цель - удалить предупреждение с консоли (чтобы обезвредить его, нужно меньше спама).

В частности, я пытаюсь использовать FolderBrowse()в пакете Python3 PySimpleGUI на MacOS Мохаве.Это выдает следующее сообщение (во время выполнения):

objc[2542]: Class FIFinderSyncExtensionHost is implemented in both /System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fff9408e3d8) and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride (0x1073e4f50). One of the two will be used. Which one is undefined.

Опять же, здесь я намерен игнорировать приведенное выше предупреждение, а не исправлять его самостоятельно.

Я видел другие вопросы по подавлению предупреждений Python, такие как этот

Однако я не пытаюсь скрыть группу предупреждений (например: DeprecationWarning).Вместо этого я хочу скрыть только одно предупреждение, показанное выше.

edit, код, который я использую:

import PySimpleGUI as sg
window_rows = [[sg.InputText(), sg.FolderBrowse()]]
sg.Window('', window_rows).Read()

Ответы [ 3 ]

0 голосов
/ 29 июня 2019

Метод 1 - если tkinter использует модуль «Предупреждения»

На странице со ссылкой, предоставленной OP, описана методика, которая подавляет отдельные предупреждающие сообщения.

К сожалению, я не могу продублировать ваше предупреждение на компьютерах с Windows или Linux, поэтому я не могу сказать, сработает ли это исправление, но вот так:

import warnings
warnings.filterwarnings('ignore', message='Class FIFinderSyncExtensionHost is implemented in both')

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

Что хорошего в этом решении, так это то, что существует так много способов получить индикатор, что его следует игнорировать. В приведенном выше примере я принял участие в сообщении об ошибке и использовал его при вызове filterwarnings. Позволяет легко фильтровать одно предупреждение или группу из них.

Вот небольшая демонстрационная программа, которая генерирует предупреждение, а также демонстрирует, как текст может использоваться для его фильтрации.

import PySimpleGUI as sg
import warnings

layout = [[sg.Text('My Text Editor')],
          [sg.B('Enable Filter'), sg.B('Warning')],]

window = sg.Window('My Text Editor', layout)

while True:             # Event Loop
    event, values = window.Read()
    if event is None:
        break
    print(event, values)
    if event == 'Warning':
        warnings.warn("my warning goes here")
    elif event.startswith('Enable'):
        warnings.filterwarnings('ignore', message='my warning')

window.Close()

Документация Python описывает предупреждения, модулированные здесь: https://docs.python.org/3.6/library/warnings.html#warnings.filterwarnings

И эта страница хорошо объяснила некоторые из понятий: https://pymotw.com/2/warnings/


Метод 2 - Перенаправление STDERR и / или STDOUT

Поскольку вышеописанный метод № 1 ничего не исправил, вы можете перенаправить stderr и / или stdout во время отображения оскорбительного сообщения.

Вот небольшая тестовая программа, которая перенаправит и восстановит как stderr, так и stdout и снова вернет их в нормальное состояние. Используйте его, чтобы отключить один или другой и попытаться сделать FileBrowse, пока один из них повторно. По крайней мере, это скажет вам, отображается ли он на stdout, stderr или на обоих.

import PySimpleGUI as sg
import sys

sg.ChangeLookAndFeel('GreenTan')
layout = [  [sg.In(), sg.FileBrowse()],
            [sg.OK(), sg.B('StdErr Reroute'), sg.B('StdOut Reroute'), sg.B('Restore')]]

window = sg.Window('My new window', layout)

temp_stderr = temp_stdout = None
while True:             # Event Loop
    event, values = window.Read()
    if event is None:
        break
    elif event.startswith('StdErr'):
        temp_stderr = sys.stderr
        sys.stderr = None
    elif event.startswith('StdOut'):
        temp_stdout = sys.stdout
        sys.stdout = None
    elif event == 'Restore':
        if temp_stderr:
            sys.stderr = temp_stderr
            temp_stderr = None
        if temp_stdout:
            sys.stdout = temp_stdout
            temp_stdout = None
    print(event, values)

Когда вы запустите это, нажмите кнопку OK после перенаправления вывода, вы увидите, что на консоли ничего не распечатывается. Восстановите его снова, затем нажмите OK, и вы снова увидите вывод.

Если вы можете окружить только тот объем кода, который вызывает проблему, перенаправив его в никуда, а затем восстановив снова, этот метод должен сработать.

Если вы не можете временно перенаправить маршрут, то вы можете создать класс, который перенаправит stdout и stderr в ваш класс. Это даст вам полный контроль над фильтрацией, чтобы при отображении предупреждения вы не позволяли этим символам выходить на официальный stdout / stderr, а для всего остального, через что вы передаете данные.

0 голосов
/ 29 июня 2019

См. Раздел Временное подавление предупреждений в документации модуля warnings:

Если вы используете код, который, как вы знаете, вызоветпредупреждение, такое как устаревшая функция, но не желающее видеть предупреждение (даже если предупреждения были явно настроены через командную строку), тогда можно подавить предупреждение с помощью диспетчера контекста catch_warnings:

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

Пока в диспетчере контекста все предупреждения будут просто игнорироваться.Это позволяет использовать известный устаревший код без необходимости видеть предупреждение, не подавляя предупреждение для другого кода, который может не знать об использовании устаревшего кода.(...)

Кажется, это именно то, что вам нужно, не так ли?

0 голосов
/ 26 июня 2019

Я не знаком с PySimpleGUI и поэтому не знаю, как заставить замолчать это предупреждение из Python.Подумайте о том, чтобы «заставить замолчать» предупреждение, просто игнорируя конкретный текст внутри него:

python myfile.py 2> >(grep -v 'FIFinderSyncExtensionHost' 1>&2)

Это, конечно, предполагает, что вы запускаете Python из терминала.Кроме того, если в предупреждении используется stdout, а не stderr, вам придется использовать

python myfile.py | grep -v 'FIFinderSyncExtensionHost'

.

...