• 同时安装PyQt4和PyQt5之sip版本区分


    如果同时安装了PyQt4和PyQt5(自己编译或者安装预编译版本),在运行某个PyQt4或者PyQt5的Python脚本时,很有可能出现以下的错误提示:

    RuntimeError: the sip module implements API vX.X but the PyQt5.QtCore module requires API vY.Y

    本文帮助大家解决这个问题。

    ==========================================================

    1. 什么是sip?

    sip是RiverBank(也就是PyQt的开发商)开发的用于PyQt的Python/C++混合编程解决方案。由于Qt框架的复杂性,PyQt并没有使用Cython、SWIG的混合编程方案,而是自己单独做了一套框架。sip包括一个sip工具、SDK和Python Module。

    与SWIG类似,使用sip也需要先编写一个『配置文件』,然后使用sip工具『编译』为C++源文件,最后,和Qt库一起编译形成适用于Python的PyQt。

    与SWIG不同的是,sip同时以Python Module的形式存在,也就是说,作为Python Module的PyQt,依赖于作为Python Module的sip。而对于SWIG,一旦自动生成的C++生成完毕,整个流程就不再依赖SWIG了。

    2. sip和PyQt的版本依赖

    本文写作之时,PyQt4的最高版本为4.8.7,与Qt4的最高版本相同;PyQt5的最高版本为5.5.0,略低于Qt5的最高版本5.5.1;而sip的版本为4.16.9,和PyQt的版本在字面上无关联。

    在sip内部还有sip的API版本,作为C API的宏SIP_API_MAJOR_NR和SIP_API_MINOR_NR定义于sip.h。每个sip版本的API的版本是固定的,每个PyQt版本所需要的sip API版本是一个范围。如果PyQt想正常运行,sip的API版本必须落在该PyQt版本所需要的sip API版本的范围内。这个范围是这样规定的:

    1 API的主版本号必须相同。(主版本号不互相兼容原则)
    2 API的副版本号,PyQt版本所需的值不可大于sip提供的值。(副版本号仅向下兼容原则)

    例如,

    1 某PyQt在编译时选取的sip的API版本号为8.0,那么它可以在API的版本号为8.1的sip的支持下运行。
    2 某PyQt在编译时选取的sip的API版本号为8.1,那么它不可以在API的版本号为8.0的sip的支持下运行。
    3 某PyQt在编译时选取的sip的API版本号为9.0,那么它不可以在API的版本号为10.0的sip的支持下运行。
    4 某PyQt在编译时选取的sip的API版本号为10.0,那么它不可以在API的版本号为9.0的sip的支持下运行。

    那么sip的API版本和sip自身的版本有何关系?RiverBank的文档是这么说的:

    SIP_API_MAJOR_NR

    This is a C preprocessor symbol that defines the major number of the SIP API. Its value is a number. There is no direct relationship between this and the SIP version number. 

    SIP_API_MINOR_NR

    This is a C preprocessor symbol that defines the minor number of the SIP API. Its value is a number. There is no direct relationship between this and the SIP version number.

    ……

    某系统已经安装了sip,想知道可以支持哪些版本的PyQt?

    最好的办法似乎是:

    1 启动python, import sip 并 print sip.SIP_VERSION_STR,得到sip的版本
    2 去PyQt download 观看与这个版本的sip发布年代相近的PyQt

    (如果有读者能提供更好的经验欢迎指点)

    3. PyQt4和PyQt5共享sip之不可能

    我们假设这样一种情况:

    某系统自带了版本为4.7.1的PyQt4,以及对应的sip(版本4.14,API版本9.0)。今欲安装最新的PyQt 5.5.0。发现编译过程需要sip 4.16,API版本11.2,于是下载和重新编译sip 4.16,勉强编译通过,但安装时犯了难,因为不存在同时能够支持PyQt4.7和PyQt5.5的sip!

    当然,可能的解决方法有

    1 换个系统
    2 virtualenv
    3 升级PyQt4到最新4.8.7,feature是能够向下兼容4.7.1的

    有没有不那么兴师动众的方法?

    4. 问题之解决

    事实上,只需要让PyQt4和PyQt5各用自己的sip就行了。

    第一步,找到sip的安装位置。通常的位置是Python的site-packages,其文件名为sip.pyd(Windows)或者 sip.so (*nix)。例如,在Windows下,其位置为C:Python27Libsite-packagessip.pyd,在Linux(Ubuntu)下,其位置为/usr/lib/python2.7/dist-packages/sip.****.so;在macOS下,其位置为/Library/Python/2.7/site-packages/sip.so(对于系统自带的Python)

    第二步,把sip移动到对应版本的PyQt目录内。例如,若sip和PyQt4匹配而与PyQt5不匹配,就把sip放到PyQt4的安装目录内。

    第三步,编译不匹配的PyQt版本并安装,但不要安装sip,而是把sip的python module直接放入对应的PyQt的安装目录内。

    到了这一步,PyQt4和PyQt5的安装目录有了各自对应的sip。此时若import PyQt4或者import PyQt5,会遇到sip无法找到的问题。没有关系。我们利用__init__.py这个文件,在import PyQtX之时自动找到对应版本的sip。方法是这样的:

    打开PyQtX/__init__.py(X是4和5,每个PyQt都需要做),默认情况下这个文件只有PyQt的版权声明。在下面填上几句:

    1 import sys
    2 import os
    3 sys.path.append(os.path.realpath(os.path.dirname(__file__)))

    我们知道,PyQt的核心module都是以动态链接库形式存在。你import PyQt4的时候,在加载动态链接库之前,Python会发现PyQt4/__init__.py并加以执行。这样,当动态链接库(比如QtCore)寻找sip的时候,它总会在自己所在的目录找到正确版本的sip。

  • 相关阅读:
    Java学习笔记(一)语法
    【转,整理】C# 非托管代码
    HTML5学习笔记(七)WebSocket
    HTML5学习笔记(七)HTML5 服务器发送事件(Server-Sent Events)
    MySQL修改表格内容3
    MySQL修改表格内容2
    MySQL修改表格内容
    MySQL创建表格
    if-else if-else;多选择结构
    面向对象和面向过程的初步概念
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14022826.html
Copyright © 2020-2023  润新知