Matlab生成的Python包装与Ubuntu上的Pyqt5冲突 - 可能的库问题



我正在使用ubuntu 18.04和pyqt 5.12.1构建一个应用程序,该应用程序导入从MATLAB代码生成的Python软件包(这些软件包取决于MATLAB运行时(。Python中的MATLAB软件包需要设置LD_LIBRARY_PATH环境变量;没有此,该程序将在进口MATLAB生成的软件包时提出例外。

但是,我发现在设置LD_LIBRARY_PATH时PYQT无法运行。该程序在安装MATLAB运行时运行良好,只要未导入MATLAB软件包并且未设置LD_LIBRARY_PATH

在MATLAB运行时安装程序的提示

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)"

/usr/local/MATLAB/MATLAB_Runtime/v96/bin/glnxa64/中的MATLAB运行时船libQt5XcbQpa.so.5,必须将其导出到LD_LIBRARY_PATH。在设置LD_LIBRARY_PATH时,PYQT似乎正在使用它,并且是一个旧版本,与当前版本的Pyqt。

不兼容。

另一个具有相同名称的库是在/usr/lib/x86_64-linux-gnu/中,它与MATLAB版本具有不同的MD5校验和。但是,将此目录添加到LD_LIBRARY_PATH的开始无济于事。设置QT_QPA_PLATFORM_PLUGIN_PATH也无济于事。

有没有一种方法可以使/usr/lib/x86_64-linux-gnu/中的版本比MATLAB供列表更高的优先级?有其他方法可以解决此问题吗?

我发现了一个解决方法:

  • 在新过程中运行所有MATLAB包装的代码;这几乎没有不便,因为计算必须在单独的线程或过程上进行,以防止GUI冻结GUI。
  • 在运行MATLAB包装代码的每个过程中,在导入MATLAB模块之前以编程方式设置LD_LIBRARY_PATH环境变量。导入语句必须处于函数而不是文件的顶部。

这是一个相对最小的示例:

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),))

最新更新