前言
在 Python 3 下使用 PyQt5 相当方便,有现成的 pip 包。在 Python 2 64-bit 下也可以通过非官方的 pip 包来凑合使用一下 PyQt5。可惜的是,我的项目依赖的 .pyd 文件居然是在 Python 2.7 32-bit 环境下编译的。都TMD的 9021 年了,还在用 32-bit Python2,开发人员估计都是懒癌晚期,TeraSense 迟早药丸。
没办法自己动手编译吧!
编译前,重要的事情说三遍:
看网上各种教程之前,放一个官方教程在旁边参考!
看网上各种教程之前,放一个官方教程在旁边参考!
看网上各种教程之前,放一个官方教程在旁边参考!
>> Building and Installing from Source <<
所需组件
-
Visual Studio 2019 Community
我们要用其 Developer Command Prompt VS 2019 来编译 -
Python 2.7.16
PyQt5 最终安装的地方 -
Qt 5.11.3
辅助编译工具 -
SIP 4.19.17
连接 Python 和 PyQt 的驱动包 -
PyQt 5.11.3
源代码
组件版本说明
这么多组件协同工作,大家的版本之间互相匹配是编译成功的关键。版本配置的总体思路是:Qt 是关键,它是在什么配置下编译生成的,其他各个组件就得找相同版本。上面组建的版本也是根据这个思路找好的。所以记住这个思路,换一个版本编译也能找到匹配的组件版本。
- 下载安装 Python 2.X_x86,
X
是你想要的版本,这里就选择了最新的 Python 2.7.15 (明年 Python 2 就不更新了,还用它干啥?!再次吐槽 TeraSense)。x86
是因为必须要用 32-bit 的 Python,没办法。 - 下载安装 qt-unified-windows-x86-3.1.1-online.exe. 选择
unified
的安装版本是因为你可以在其安装向导里查看各个 Qt 版本的信息。windows
,必然的,要在 Windows 下安装。x86
,是配合 Python x86。online
,只下载一次程序,方便选择性安装 Qt。
可以看到我选的是 Qt 5.11.3,因为再高的版本编译 32-bit 的时候就用的是 MSVC 2017 32-bit 了。而我比较懒,电脑安装 Visual Studio 2019 的时候,装了 MSVC 2015 32-bit。所以就选 Qt 5.11.3 好了。如果你有 MSVC 2017 32-bit 那也可以装更高版本的 Qt。 - 下载 PyQt 5。其本号 x.xx.yy 中 x.xx 一定要对应 Qt 的版本。我这里 Qt 5.11.3 就选择了 PyQt 5.11.3。
- 下载 SIP。这个的版本号我还没有找到选择的方法。不过因为我选的 PyQt 5.11.3 还比较新,而 SIP 又是用来驱动 PyQt 的,所以我选了 最新的 SIP 4.19.17。
- 下载安装 Visual Studio 2019 Community。
在安装 VS 2019 的时候选上图中的 C++ 模块。可以看到右边就带有了MSVC v142,也就是 MSVC 2015 了。
编译
好了,组件们都各就各位了,下面开始愉(man)快(chang)的编译吧。
注意,我们的所有编译操作都要在 Developer Command Prompt VS 2019 里进行,不能用 Windows 自带的命令提示符。
预备
- 解压
sip-4.19.17.zip
和PyQt5_gpl-5.11.3.zip
- 在 Developer Command Prompt VS 2019 先敲
nmake -help
看看是否报错。如果你安装 VS 2019 的时候选了 C++ 模块,应该不会报错。 - 设置好环境变量,如下图高亮部分
这里推荐使用 Rapid Environment Editor,省心好工具!
编译 SIP
在 Developer Command Prompt VS 2019 里执行以下操作,记得按需修改对应路径。
set LIB=%LIB%;C:\Python27\libs;
cd C:\Users\psych\Downloads\sip-4.19.17
python configure.py ^
--sip-module PyQt5.sip
nmake
nmake install
python configure.py --sip-module PyQt5.sip
是编译前的设置。nmake
是编译。nmake install
是将编译好的东西安装到 Python 里去。
编译 PyQt5
set LIB=%LIB%;C:\Qt\5.11.3\msvc2015\lib;C:\Python27\libs;
set PATH=%PATH%;C:\Qt\5.11.3\msvc2015\bin;
cd C:\Users\psych\Downloads\PyQt5_gpl-5.11.3
python configure.py ^
--sip=..\sip-4.19.17\sipgen\sip.exe ^
--sip-incdir=..\sip-4.19.17\siplib ^
--disable=QtNfc ^
--qmake=C:\Qt\5.11.3\msvc2015\bin\qmake.exe ^
--verbose
namek
nmake install
--sip=..\sip-4.19.17\sipgen\sip.exe
指定了sip.exe
程序。
--sip-incdir=..\sip-4.19.17\siplib
指定 siplib
路径。
--disable=QtNfc
这个是 PyQt5 的一个模块,一般好像不需要,我看参考的 blog 里都说不禁掉就报错,大家都禁掉了,我也就照做了。
--qmake=C:\Qt\5.11.3\msvc2015\bin\qmake.exe
指定了 qmake.exe
的路径。
--verbose
打印详细信息。
打包整理
由于 nmake install
安装的 PyQt5 只是把 编译生成的文件 copy到了 Python site-packages 的 PyQt5 文件夹下,bat,exe 和 dll 文件需要我们手动复制相应的文件到 PyQt5 对应的位置。
建议使用 everything 这个软件,可以快速定位 Windows 上的文件。
复制以下相应的文件到 Python 下对应的位置,如果 Python 下对应的位置 有其文件了,就不需要复制了。
- Plugins
复制C:\Qt\5.11.3\msvc2015\plugins\
到C:\Python27\Lib\site-packages\PyQt5\plugins\
。可能会有3种文件,只保留xxx.dll
,删除xxxd.dll
和xxxd.pdb
文件。 *.dll
复制C:\Qt\5.11.3\msvc2015\bin\
下全部内容到C:\Python27\Lib\site-packages\PyQt5\
。
同上,包括xxx.dll
,.exe
等文件。不要复制xxxd.dll
,.pdb
。- sip lib
C:\Users\psych\Downloads\sip-4.19.17\siplib
中的sip.pyd
或sip.so
复制到C:\Python27\Lib\site-packages\PyQt5\
。 - sip 包
将这4个文件复制进C:\Python27\Lib\site-packages\PyQt5\
。同时将其复制到 site-packages 下。 .bat
文件
复制C:\Users\psych\Downloads\PyQt5_gpl-5.11.3
里的pylupdate5.bat
、pyrcc5.bat
和pyuic5.bat
到C:\Python27\
。
编辑 C:\Python27\Lib\site-packages\PyQt5\__init__.py
import sys
import os
pyqt5_path = os.path.realpath(os.path.dirname(__file__))
sys.path.append(pyqt5_path)
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = pyqt5_path + '/plugins/platforms'
os.environ['QT_PLUGIN_PATH'] = pyqt5_path + '/plugins'
测试
在 Developer Command Prompt VS 2019 里或者 Windows 自带的命令提示符运行以下代码测试是否安装成功。
import sys
from PyQt5 import QtWidgets
def main(argv):
app = QtWidgets.QApplication(argv)
app.lastWindowClosed.connect(app.quit)
gui = QtWidgets.QWidget()
gui.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main(sys.argv)
PyQt5 移植
- 参考 预备 章节,将 Python 的路径设置好。
- 将以下文件复制到其他 Windows PC 的 python27 32-bit 的对应文件夹中
C:\Python27\
pylupdate5.bat
pyrcc5.bat
pyuic5.bat
sip.exe
sip\
C:\Python27\include\
sip.h
C:\Python27\Lib\site-packages\
enum\
enum34-1.1.6.dist-info\
PyQt5\
PyQt5_sip-4.19.17.dist-info\
sipconfig.py
sipdistutils.py
复制 PyQt5 和 sip 到 site-packages复制 3 个.bat
文件到python.exe
同级目录复制sip.h
到 Python 的 include 目录下
配置环境变量。编辑 C:\Python27\Lib\site-packages\PyQt5\__init__.py
QT_QPA_PLATFORM_PLUGIN_PATH
QT_PLUGIN_PATH
后续工作
有可能你在编译好之后还要随你的代码一起打包为 .exe
文件,可以参考 使用Py2exe将PyQt程序打包为exe文件。我还没有到那一步,所以也是先在这里 mark 一下。
总结
整个编译过程分三步
- 下载组件。
再次说一下思路是,注意和之前说的不一样,下载最新Python >> 下载最新的 PyQt 和 SIP 源代码 >> 下载和 PyQt 版本号一样的 Qt >> 下载 Visual Studio 以及和 Qt 一样的 MSVC。 - 编译
主要就是设置好 SIP 和 PyQt5 的两个 configure.py 的参数。 - 打包整理
需要挨个检查文件,比较繁琐。
感谢
在这里我要深深感谢一下我的老婆掰掰 神力之手 的护法加持,以及亲自买回来的美味午饭。有了这些帮助,我的编译工作才得以正常进行!
参考
我在这里整理一下我看过的参考。如果你按照我的方法没有成功,我相信下面所有的参考都看一遍你也就懂得如何找到正确编译方法了。
英文参考
- Use the Microsoft C++ toolset from the command line
补充一下对 Developer command prompt 的了解 - NMAKE Reference
补充一下对 NMAKE 的了解
先看 How to install PyQt5 for Python 2.7 on Windows 对整体思路有一个了解。之后看一下 stack overflow 上的 问题讨论 (中文翻译本) 以及其中提到个各种参考链接。
最后可以看一下几个不是很重要的:
- https://blog.abstractfactory.io/pyqt5-1-1-for-python-2-7/ (文章有点老了)
- https://fredrikaverpil.github.io/2015/11/25/compiling-pyqt5-for-python-2-7-on-os-x/ (在 OS X 上的编译方法)
中文参考
中文的就看 PyQt5 编译PyQt5 (python27, windows x64) 以及文中所提到的参考链接应该就足够了。
另外还有两个拓展阅读:
特别说明
因为我看的这些参考都很老了。我写的这篇估计是数一数二的新版本了。所以在编译最后还出现了一个小问题,PyQt5 error “PyCapsule_GetPointer called with incorrect name”。原因呢,没有看官方文档啊!还是那句话
看网上各种教程之前,放一个官方教程在旁边参考!
看网上各种教程之前,放一个官方教程在旁边参考!
看网上各种教程之前,放一个官方教程在旁边参考!
附录
- Full compiling script
#####################
# Compile sip
#####################
cd C:\Users\psych\Downloads\sip-4.19.17
set QMAKESPEC=C:\Qt\qt-5.6.0-x86-msvc2013\5.6\msvc2013\mkspecs\win32-msvc2013
set LIB=%LIB%;C:\Python27\libs;
python configure.py ^
--platform=win32-msvc2015 ^
--sip-module PyQt5.sip ^
--no-tools
nmake
nmake install
#####################
# Compile PyQt5
#####################
cd C:\Users\psych\Downloads\PyQt5_gpl-5.11.3
set QMAKESPEC=C:\Qt\qt-5.6.0-x86-msvc2013\5.6\msvc2013\mkspecs\win32-msvc2013
set LIB=%LIB%;C:\Qt\5.11.3\msvc2015\lib;C:\Python27\libs;
set PATH=%PATH%;C:\Qt\5.11.3\msvc2015\bin;
python configure.py ^
--sip=..\sip-4.19.17\sipgen\sip.exe ^
--sip-incdir=..\sip-4.19.17\siplib ^
--disable=QtNfc ^
--qmake=C:\Qt\5.11.3\msvc2015\bin\qmake.exe ^
--verbose
namek
nmake install
#####################
# Test
#####################
python
from PyQt5 import QtCore, QtGui, QtWidgets
cd C:\Users\psych\Downloads
python testgui.py