Игнорировать исключение при импорте и продолжить с остальной частью модуля? - PullRequest
0 голосов
/ 12 января 2019

У пакета Python, который я разрабатываю, есть зависимость (pyfluidsynth), которая нарушается в моей системе, вызывая ошибку AttributeError при импорте. Pyfluidsynth - это оболочка для библиотеки C «fluidsynth», и причина ее поломки в том, что она пытается обернуть пару функций C, которых нет в библиотеке, по крайней мере, для версии fluidsynth в моей системе.

Это оскорбительные строки кода:

fluid_synth_set_reverb_full = cfunc('fluid_synth_set_reverb_full', c_int,
                                    ('synth', c_void_p, 1),
                                    ('set', c_int, 1),
                                    ('roomsize', c_double, 1),
                                    ('damping', c_double, 1),
                                    ('width', c_double, 1),
                                    ('level', c_double, 1))

fluid_synth_set_chorus_full = cfunc('fluid_synth_set_chorus_full', c_int,
                                    ('synth', c_void_p, 1),
                                    ('set', c_int, 1),
                                    ('nr', c_int, 1),
                                    ('level', c_double, 1),
                                    ('speed', c_double, 1),
                                    ('depth_ms', c_double, 1),
                                    ('type', c_int, 1))

... и ошибка, которую я получаю:

AttributeError: /lib64/libfluidsynth.so.1: неопределенный символ: fluid_synth_set_reverb_full

Это достаточно легко исправить: я не использую эту функциональность, поэтому я могу просто окружить два оператора попыткой / за исключением моей копии библиотеки fluidsynth. Но при распространении собственного пакета я не могу полагаться на версию pyfluidsynth в pypi, поскольку она будет работать по крайней мере на компьютерах некоторых людей.

Эта проблема была подана, но разработчик pyfluidsynth еще не исправил ее. Между тем, есть ли способ, которым я могу импортировать pyfluidsynth так, чтобы он перехватывал исключения, игнорировал их и продолжал импортировать остальную часть модуля?

1 Ответ

0 голосов
/ 12 января 2019

Вы можете разветвляться pyfluidsynth и зависеть от этого, пока не будет исправлено. Это, вероятно, лучший вариант, чем monkeypatching. Pip может устанавливать пакеты, размещенные на GitHub, если вы не хотите устанавливать его на PyPI. Используйте git+https URL-адрес для хранилища (и ветвь, если необходимо) вместо только имени пакета.


Тем не менее, вы, вероятно, можете использовать unittest.mock.patch , чтобы заменить ctypes.CFUNCTYPE версией, которая возвращает прототип обернутой функции, которая проверяет fluid_synth_set_reverb_full или fluid_synth_set_chorus_full и возвращает фиктивное значение в тех случаях, но в противном случае делегаты реального прототипа.

Может быть, что-то вроде

from unittest.mock import patch
from cytpes import CFUNCTYPE

def patched_CFUNCTYPE(*args):
    real_prototype = None
    def wrapped_prototype(*a):
        nonlocal real_prototype
        if a[0][0] in {
            'fluid_synth_set_reverb_full',
            'fluid_synth_set_chorus_full',
        }:
            return None
        if not real_prototype:
            real_prototype = CFUNCTYPE(*args)
        return real_prototype(*a)
    return wrapped_prototype

try:
    import fluidsynth
except AttributeError:
    with patch('ctypes.CFUNCTYPE', patched_CFUNCTYPE):
        import fluidsynth

Не проверял это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...