pyqt编写的程序如何发布

2009年12月3号研究了一下如何发布pyqt的程序,整理内容如下:

pyqt是qt图形库对于python编程语言的一个绑定,qt是著名的跨平台图形开发库,专业,易用,以及企业级别支持,文档齐全。python是一个简单易用的解释语言。不过这篇文章是关于如何发布pyqt程序的,那么读者应该都知道这些,我就不多介绍了。

我们用pyqt开发完程序的时候,得到的是一堆python源代码,以及一些资源文件,比如用到的图片,声音什么的。程序在我们开发平台上可以运行,但是我们还需要想办法让客户机也能够用我们的代码。

我们需要做2件事情:一个是把源代码打包成可以放到任何电脑都能够执行的程序,另一个是做一个安装程序,好方便安装到客户机上。

我现在选择py2exe作为打包的工具,nsis作为生成安装程序的工具。

py2exe

nsis

nsis下载后文档中有详细的介绍,安装目录中含有许多的示例。

我写的示例在 这里

稍微解释一下: 比如,我写了一个新的专案,名称叫test_pyqt,新建了一个这样的文件夹。 里面有一个main.py源代码。同时还有一个res的资源目录。 为了能够利用py2exe打包,需要新建一个setup.py的设置文件。

几个难点整理如下: 根据py2exe里面说的,pyqt需要包含sip(我也不知道这是什么东西,估计是C++转python的时候要用到的。。),下面的脚本含有具体的设置。 编译好的文件还需要一些额外的dll文件(主要是针对没有加sp的XP版本运行时出现“程序出错”报错的状况),放在dll文件夹里面,打包的时候要加上(dll文件在上面的示例中)。我没有研究出如何把这些文件加到可执行文件里面的办法,如果你知道的话,就告诉我。

内容如下:

          #!/usr/bin/env python
          #-*- coding:utf-8 -*-
          # ---------------------------------
          # 打包程序
          
          from distutils.core import setup
          import py2exe,glob
          
          setup(windows=[{
                          "script": 'main.py',
                          #应用程序图标
                          "icon_resources":[(1, "res/py.ico")] }],
                data_files=[
                            #资源文件
                            ("res", glob.glob("res/*.*")),
                            #因为客户机可能缺少部分开发文件造成无法运行程序,需要打包一些文件
                            (".",glob.glob("dlls/*.*")),
                            ],
                options={"py2exe":{"includes":["sip"],
                                   "optimize":2,
                                   #打包成一个文件,加快读取速度
                                   "compressed":1,
                                   "bundle_files":2,
                                   #文件放在哪里
                                   "dist_dir":"temp/dist",
                                   #少了个文件,不管它
                                   "dll_excludes":["MSVCP90.dll"],
                                   },
                         },
                zipfile=None,)#一个文件
          
          #删除build临时目录
          import shutil
          shutil.rmtree('build')
          

执行:

          python setup.py py2exe
          

以上语句需要把python的目录加到path里面去,或者你可以在python前加上完整的python安装目录. 我是加path的,因为这样使用python更方便。

之后,会生成temp/dist文件夹,里面就是一个main.exe可执行文件了,还有res文件夹。

之后是生成安装文件,新建一个installer.nsi文件,内容如下(因为比较长,放到最后)。

内容比较多。当时我在做的时候,看了很多的文档才知道具体怎么做。为了方便,你还是用我的示例吧。

下面的内容含有多语言,license页面,安装内容页面,安装目录页面,以及反安装页面。

如果你感兴趣的话可以自己研究,我是被nsis细节给累倒了。

这个文件你只需要改下面软件名称的部分,它会自动把dist打包安装到program files里面,生成执行文件链接到桌面以及菜单项中。

对了,主执行文件的入口是main.py这个源代码。

文件写好后,鼠标右键菜单中有一个compile nsis script的选项,点击就可以生成安装文件。

具体的细节可以看我上面示例的压缩文档。我写了一个makefile来方便快速执行操作(别告诉我你不会用make)。 该示例在windows xp,python2.6,nsis2.46,pyqt4.5,py2exe上测试通过。等以后考虑跨平台版本:

          #coding:utf-8
          
          ;软件名称
          !define NAME "test_pyqt"
          
          ;主执行文件
          !define EXE "dist\main.exe"
          
          ;样式
          XPstyle on
          
          ;输出的安装文件
          OutFile "temp/${NAME}_installer.exe"
          
          ;默认目录
          InstallDir $PROGRAMFILES\${NAME}
          
          ; 检查是否已经安装过
          InstallDirRegKey HKLM "Software\${NAME}" "Install_Dir"
          
          ;需要管理员权限
          RequestExecutionLevel admin
          
          ;--------------------------------
          
          ; 页面
          
          Page license
          Page components
          Page directory
          Page instfiles
          
          UninstPage uninstConfirm
          UninstPage instfiles
          
          ;--------------------------------
          
          ; 安装主目录
          Section "main"
          
          SectionIn RO
          
          ; Set output path to the installation directory.
          SetOutPath $INSTDIR
          
          ; 需要安装的程序
          File /r "temp\dist"
          
          ; Write the installation path into the registry
          WriteRegStr HKLM SOFTWARE\${NAME} "Install_Dir" "$INSTDIR"
          
          ; Write the uninstall keys for Windows
          WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "DisplayName" "${NAME}"
          WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
          WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoModify" 1
          WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoRepair" 1
          WriteUninstaller "uninstall.exe"
          
          SectionEnd
          
          ; 开始菜单
          Section "开始菜单"
          
          CreateDirectory "$SMPROGRAMS\${NAME}"
          CreateShortCut "$SMPROGRAMS\${NAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
          SetOutPath $INSTDIR\dist
          CreateShortCut "$SMPROGRAMS\${NAME}\${NAME}.lnk" "$INSTDIR\${EXE}" "" "$INSTDIR\${EXE}" 0
          
          SectionEnd
          
          ; 桌面快捷方式
          Section "桌面快捷方式"
          SetOutPath $INSTDIR\dist
          CreateShortCut "$DESKTOP\${NAME}.lnk" "$INSTDIR\${EXE}" "" "$INSTDIR\${EXE}" 0
          SectionEnd
          
          ;--------------------------------
          
          ; Uninstaller
          
          Section "Uninstall"
          
          ; Remove registry keys
          DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
          DeleteRegKey HKLM SOFTWARE\${NAME}
          
          ; Remove directories used
          Delete "$DESKTOP\${NAME}.lnk"
          RMDir /r "$SMPROGRAMS\${NAME}"
          RMDir /r "$INSTDIR"
          
          SectionEnd
          
          ;--------------------------------
          ; 语言部分
          ; First is default
          LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
          LoadLanguageFile "${NSISDIR}\Contrib\Language files\SimpChinese.nlf"
          
          ; License data
          ; Not exactly translated, but it shows what's needed
          LicenseLangString myLicenseData ${LANG_ENGLISH} "license.txt"
          LicenseLangString myLicenseData ${LANG_SIMPCHINESE} "license.txt"
          LicenseData $(myLicenseData)
          
          ; Set name using the normal interface (Name command)
          ; LangString Name ${LANG_ENGLISH} "English"
          ; LangString Name ${LANG_SIMPCHINESE} "Simplified Chinese"
          ; Name $(Name)
          
          ;--------------------------------
          Function .onInit
          
          ;Language selection dialog
          
          Push ""
          Push ${LANG_ENGLISH}
          Push English
          Push ${LANG_SIMPCHINESE}
          Push "Simplified Chinese"
          Push A ; A means auto count languages
          ; for the auto count to work the first empty push (Push "") must remain
          LangDLL::LangDialog "Installer Language" "Please select the language of the installer"
          
          Pop $LANGUAGE
          StrCmp $LANGUAGE "cancel" 0 +2
          Abort
          FunctionEnd
          [/sourcecode]
          

2010/10/29修改: 其实现在pyinstaller用起来更方便, 直接build就可以了. python2.6以后的版本需要下载开发版本使用.

建立时间: 2010/10/29 21:06:00

blog comments powered by Disqus
===>