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

摘要:
与SWIG不同,sip也以Python模块的形式存在,即PyQt作为Python模块依赖于sip作为Python模块。如果PyQt想要正常运行,sip API版本必须在PyQt版本所需的sip API版本范围内。我们将安装最新的PyQt5.5.0。发现编译过程需要sip 4.16和API版本11.2,所以我们下载并重新编译了sip 4.16,它几乎没有通过编译,但很难安装,因为没有sip可以同时支持PyQt4.7和PyQt5.5!此时,PyQt4和PyQt5的安装目录有自己的sip。此时,如果使用importPyQt4或importPyQt5,则会遇到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。

免责声明:文章转载自《同时安装PyQt4和PyQt5之sip版本区分》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇《【GraphTER】通过逐点变换实现无监督图神经网络共变特征学习》MySQL日志系统(redo log、undo log、binlog)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

日志回滚:python(日志分割)

日志回滚:python 什么是日志回滚? 答: 将日志信息输出到一个单一的文件中,随着应用程序的持续使用,该日志文件会越来越庞大,进而影响系统的性能。因此,有必要对日志文件按某种条件进行切分,要切分日志文件。 分割日志的触发条件:大小、日期,或者大小加上日期。 说是切分,实际上是,当一个日志文件达到触发条件后,对日志文件进行重命名,之后再新建原来名称的日志...

git_stats安装及使用

 git_stats是仓库代码统计工具,今天我们要求用git_stats工具做项目的代码统计,也是一步一坑的找到了一些方法,在这里记录一下 Window环境安装与使用 git_stats可以在windows和linux使用,但是集成方式有点不太一样,我目前尝试的是win版本的,在这里就先记录win版本的安装及使用,Linux环境的后期需要可以再补充 git...

ASP.NET Web API 2系列(一):初识Web API及手动搭建基本框架

 1.导言 随着Web技术的发展,现在各种框架,前端的,后端的,数不胜数。全栈工程师的压力越来越大。 PC端,pad端,移动端App(安卓/IOS)的发展,使得前后端一体的开发模式十分笨重。因此,前后端分离是web发展的趋势,其中,RESTful API是目前前后端分离的最佳实践,ASP.NET Web API是在.NET Framework上构建RES...

python常见错误记录

1. x^y x**y 2. range(a,b,c) http://www.runoob.com/python/python-func-range.html 以a为首项(默认从0开始),c为公差(默认为1)且不超过b-1的等差数列 3. lambda匿名函数 https://blog.csdn.net/liang19890820/article/det...

Python import / pyd / dll

使用Python import 模块时, 先会在模块的搜索path里依次搜索(前面会覆盖之后出现的同名模块),次序为:  1. 程序的主目录(交互模式下当前的工作目录或 脚本文件所在的目录) 2. 环境变量 PYTHONPATH目录(如果已经进行了设置) 3. 标准链接库目录(标准库模块所在目录 C:Python27或C:Python27Libsite-p...

使用百度翻译的API接口

http://api.fanyi.baidu.com/api/trans/product/desktop 这是申请的接口地址,会得到一个APPID和一个钥密 然后下载PHP的对应的代码  有一个PHP文件,把这两个静态变量的值改一下就可以用了   用的话,只要使用一下这个方法就OK了,$from是要翻译的语言类型,中国当然是中文 $to是要翻译成什么语...