Сгенерированные MATLAB пакеты Python конфликтуют с PyQt5 в Ubuntu - возможная проблема с библиотекой - PullRequest
2 голосов
/ 25 июня 2019

Я создаю приложение, используя Ubuntu 18.04 и PyQt 5.12.1, которые импортируют пакеты Python , сгенерированные из кода MATLAB (эти пакеты зависят от среды выполнения MATLAB).Пакеты MATLAB в Python требуют установки переменной окружения LD_LIBRARY_PATH;без этого программа вызывает исключение при импорте сгенерированного MATLAB пакета.

Однако я обнаружил, что PyQt не может функционировать, если установлено LD_LIBRARY_PATH.Программа работает нормально с установленной средой выполнения MATLAB, если пакет MATLAB не импортирован и LD_LIBRARY_PATH не задано.

По подсказке установщика MATLAB Runtime я добавил это в переменные среды в моей конфигурации запуска / отладки PyCharm:

LD_LIBRARY_PATH=/usr/local/MATLAB/MATLAB_Runtime/v96/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v96/sys/os/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v96/extern/bin/glnxa64.

Это вызывает сбой вPyQt часть программы.Используя переменную окружения QT_DEBUG_PLUGINS=1, сообщение об ошибке выглядит следующим образом:

Got keys from plugin meta data ("xcb")
QFactoryLoader::QFactoryLoader() checking directory path "<redacted>/PyMODA/venv/bin/platforms" ...
Cannot load library <redacted>/venv/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64/libQt5XcbQpa.so.5: undefined symbol: _ZNK14QPlatformTheme14fileIconPixmapERK9QFileInfoRK6QSizeF6QFlagsINS_10IconOptionEE)
QLibraryPrivate::loadPlugin failed on "<redacted>/venv/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so" : "Cannot load library <redacted>/venv/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64/libQt5XcbQpa.so.5: undefined symbol: _ZNK14QPlatformTheme14fileIconPixmapERK9QFileInfoRK6QSizeF6QFlagsINS_10IconOptionEE)"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.

Важная часть:

"Cannot load library <...>/libqxcb.so: (/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64/libQt5XcbQpa.so.5: undefined symbol: _ZNK14QPlatformTheme14fileIconPixmapERK9QFileInfoRK6QSizeF6QFlagsINS_10IconOptionEE)"

Среда выполнения MATLAB поставляется libQt5XcbQpa.so.5 в /usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64/, чтодолжен быть экспортирован в LD_LIBRARY_PATH.Похоже, это используется PyQt, когда установлен LD_LIBRARY_PATH, и это старая версия, которая несовместима с текущей версией PyQt.

Другая библиотека с таким же именем находится в /usr/lib/x86_64-linux-gnu/и имеет контрольную сумму MD5, отличную от версии MATLAB.Однако добавление этого каталога в начало LD_LIBRARY_PATH не помогает.Установка QT_QPA_PLATFORM_PLUGIN_PATH также не помогает.

Есть ли способ сделать версию в /usr/lib/x86_64-linux-gnu/ более приоритетной, чем библиотека, предоставляемая MATLAB?Есть ли другой способ исправить эту проблему?

1 Ответ

0 голосов
/ 04 июля 2019

Обнаружен обходной путь:

  • Запустите весь упакованный в MATLAB код в новом процессе;это всего лишь неудобство, так как вычисления должны выполняться в отдельном потоке или процессе, чтобы все равно предотвратить зависание графического интерфейса.
  • В каждом процессе, который выполняет код, упакованный в MATLAB, программно установите переменную среды LD_LIBRARY_PATH передимпорт модулей MATLAB.Операторы импорта должны быть в функции, а не в верхней части файла.

Вот сравнительно минимальный пример:

class MyPlot(PlotComponent):
    """
    A class which inherits from a base class PlotComponent, which is 
    a subclass of QWidget. In this simple example, the window 
    gets the data and calls the function `plot(self, data)` on an 
    instance of this class. 
    """
    def __init__(self, parent):
        super().__init__(parent)
        self.queue = Queue()

    def plot(self, data):
        """Calculate the results from the provided data, and plot them."""
        fs = data.frequency

        self.times = data.times
        signal = data.signal.tolist()

        # Create the process, supplying all data in non-MATLAB types.
        self.proc = Process(target=generate_solutions, args=(self.queue, signal, fs))
        self.proc.start()

        # Check for a result in 1 second.
        QTimer.singleShot(1000, self.check_result)

    def check_result(self):
        """Checks for a result from the other process."""
        if self.queue.empty(): # No data yet; check again in 1 second.
            QTimer.singleShot(1000, self.check_result)
            return

        w, l = self.queue.get() # Get the data from the process.

        a = np.asarray(w)
        gh = np.asarray(l)

        # Create the plot.
        self.axes.pcolormesh(self.times, gh, np.abs(a))

def generate_solutions(queue, signal, freq):
    """
    Generates the solutions from the provided data, using the MATLAB-packaged
    code. Must be run in a new process.
    """
    import os

    # Set the LD_LIBRARY_PATH for this process. The particular value may
    # differ, depending on your installation.
    os.environ["LD_LIBRARY_PATH"] = "/usr/local/MATLAB/MATLAB_Runtime/v96/runtime/glnxa64:" \
    "/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v96/sys/os/glnxa64:" \ 
    "/usr/local/MATLAB/MATLAB_Runtime/v96/extern/bin/glnxa64"

    # Import these modules AFTER setting up the environment variables.
    import my_matlab_package
    import matlab

    package = my_matlab_package.initialize()

    # Convert the input into MATLAB data-types, to pass to the MATLAB package.
    A = matlab.double([signal])
    fs_matlab = matlab.double([freq])

    # Calculate the result.
    w, l = package.perform_my_calculation(A, fs_matlab, nargout=2)

    # Convert the results back to normal Python data-types so that the
    # main process can use them without importing matlab, and put them 
    # in the queue.
    queue.put((np.asarray(w), np.asarray(l),))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...