Python封装成可带参数的EXE安装包实例


Posted in Python onAugust 24, 2019

最近有一个小项目,有如下的需求:

将某几个源码文件夹进行打包,文件夹内有py文件、dll文件、exe文件等各种文件类型

打包生成的安装包,在进行安装的时候,应该能够带有参数,对配置文件进行修改配置

安装过程中,可以配置系统环境变量

能够检测环境,提示安装依赖包

整个过程要可以自动化,能够大量部署

综合考虑后,决定以下几个步骤完成:

用setup.py将源码文件夹都打包成msi安装包,这样可以使用msiexec进行静默安装

setup.py可以提示用户安装依赖包,否则安装失败

再编写一个py文件,用来静默安装msi安装包,并配置系统环境变量,接受安装参数去修改配置文件的属性

最后使用pyinstaller将所有都打包成exe文件

先来编写setup.py文件:

# coding=utf-8
from distutils.core import setup
import os
 
 
def get_all_dir(path):
  """
    获取指定路径下的所有文件
  """
  all_file = []
  for dirpath, dirnames, filenames in os.walk(path):
    for filename in filenames:
      all_file.append(dirpath)
  return all_file
 
 
if __name__ == '__main__':
  all_file = get_all_dir('A') + get_all_dir('B') # 获取相对路径下A和B两个文件夹下的所有文件
  setup(name='Example', # 所要安装的软件名
     version="1.0", # 版本
     description="This is example", # 对所安装软件的描述
     author="author", # 作者
     author_email='my email', # 邮箱
     packages=all_file, # 要打包的文件
     package_data={'': ['*.*']}, # 所有文件类型都打包
     classifiers=[
       'Development Status :: 5 - Production/Stable',
       'Operating System :: Microsoft :: Windows',
       'Natural Language :: Chinese (Simplified)',
       'Programming Language :: Python',
       'Programming Language :: Python :: 2.7',
       'Topic :: Software Development :: Libraries :: Python Modules'
     ], # 需要参照https://pypi.python.org/pypi?%3Aaction=list_classifiers,用于发布在PYPI上
     install_requires=[
       'pyserial==3.2.1'
     ], # 依赖包,如果没有安装,会提示缺少,并安装失败
     )

然后打开setup.py所在目录,并将A和B两个文件夹复制过来

打开dos窗口,并运行

python setup.py bdist_msi

运行结果如下图:

build我们不关注,直接看dist,里面有一个Example-1.0.win32.msi,这就是我们生成的msi安装包。

我们再编写一个Example.py用来配置系统环境变量,并接受安装参数修改配置文件:

# coding=utf-8
import os
import sys
import subprocess
 
config_file = r"C:\Python27\Lib\site-packages\B\lib\configuration\config.cfg"
 
import sys
from subprocess import check_call
 
 
### 设置系统环境变量所需代码
if sys.hexversion > 0x03000000:
  import winreg
else:
  import _winreg as winreg
 
ENV_VARAIABLE = 'Result_Path'
 
 
class Win32Environment:
  def __init__(self, scope):
    assert scope in ('user', 'system')
    self.scope = scope
    if scope == 'user':
      self.root = winreg.HKEY_CURRENT_USER
      self.subkey = 'Environment'
    else:
      self.root = winreg.HKEY_LOCAL_MACHINE
      self.subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
 
  def getenv(self, name):
    key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_READ)
    try:
      value, _ = winreg.QueryValueEx(key, name)
    except WindowsError:
      value = ''
    return value
 
  def setenv(self, name, value):
    key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_ALL_ACCESS)
    winreg.SetValueEx(key, name, 0, winreg.REG_EXPAND_SZ, value)
    winreg.CloseKey(key)
    try:
      check_call('''\
  "%s" -c "import win32api, win32con; assert win32api.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')"''' % sys.executable)
    except Exception as e:
      print e.message
 
 
### 设置系统环境变量所需代码 end
 
 
def search_content(str, lists):
  """
    查找str是否存在于lists中,不存在就退出程序
  """
  for i in lists:
    if str in i:
      return lists.index(i)
  print "The section not found"
  os._exit(1)
 
 
def run_command_line(command_line):
  """
    运行command line
  """
  print("run:" + command_line)
  p = subprocess.Popen(command_line, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  (stdout, stderr) = p.communicate()
  try:
    print("stdout:" + stdout)
    print("stderr:" + stderr)
  except:
    pass
 
 
def main():
  # 静默安装MSI安装包
  run_command_line("msiexec /i " + sys.path[0] + r"\Example-1.0.win32.msi /qb REBOOT=SUPPRESS")
 
  # 接受参数
  section = sys.argv[1]
  attribute = sys.argv[2]
  change = sys.argv[3]
 
  # 读取配置文件内容
  file = open(config_file, 'r')
  content = file.readlines()
  file.close()
 
  # 修改配置文件的某个属性值
  index = search_content(section, content)
  is_change = False
  for change_str in content[index + 1:]:
    if "[" in change_str:
      if not is_change:
        print "Property does not exist or not in this section"
      break
    if attribute in change_str:
      content[content.index(change_str)] = change_str[:change_str.index("=") + 1] + change + "\n"
      is_change = True
      break
 
  # 把修改后的内容写入配置文件
  file = open(config_file, 'w')
  for i in content:
    file.write(i)
  file.close()
 
 
if __name__ == "__main__":
  # 如果没有参数,就默认直接安装MSI安装包
  # 如果有参数,但是参数个数不足,直接报错退出
  if len(sys.argv) == 1 and sys.argv[0] == "commonlib.exe":
    run_command_line("msiexec /i " + sys.path[0] + r"\Example-1.0.win32.msi /qb REBOOT=SUPPRESS")
  elif len(sys.argv) != 4:
    print "Usage: commonlib.py <section> <section-attribute> <attribute-value>"
    sys.exit(1)
  else:
    main()
 
  # 设置系统环境变量
  e = Win32Environment(scope="system")
  e.setenv(ENV_VARAIABLE, r'C:\Local')
  print "Setup Success!"

现在我们用Pyinstaller来进行最后的打包。

先看一个重要的文件Example.spec

spec文件是Pyinstaller打包成EXE的配置文件,是自动生成的,这里我直接拿以前的进行修改,刚开始没有的,可以直接随便运行一次Pyinstaller来获得,直接复制我的也可以。

# -*- mode: python -*-
 
block_cipher = None
 
 
a = Analysis(['Example.py'], # 主要打包的主py文件
       pathex=['C:\\Users\\abc\\Documents'], # 打包路径
       binaries=None,
       datas=None,
       hiddenimports=[],
       hookspath=[],
       runtime_hooks=[],
       excludes=[],
       win_no_prefer_redirects=False,
       win_private_assemblies=False,
       cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
       cipher=block_cipher)
a.datas+= [('Exmaple.msi', r'C:\Users\abc\Documents\Example-1.0.win32.msi', 'DATA'),]# 附加文件,打包时加入到EXE文件中,让我们可以在py文件中调用
exe = EXE(pyz,
     a.scripts,
     a.binaries,
     a.zipfiles,
     a.datas, # 打包文件列表
     name='examlpe',# exe文件的名字
     debug=False,
     strip=False,
     upx=True,
     console=True )

打开Example.spec所在的路径,复制MSI安装包到这里,在dos窗口中运行

pyinstaller Example.spec

运行成功后,会生成build和dist两个文件夹,我们依然只看dist文件夹,里面example.exe就是我们所需要的

以上这篇Python封装成可带参数的EXE安装包实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python模拟新浪微博登陆功能(新浪微博爬虫)
Dec 24 Python
Python语言的变量认识及操作方法
Feb 11 Python
python list删除元素时要注意的坑点分享
Apr 18 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 26 Python
python高效过滤出文件夹下指定文件名结尾的文件实例
Oct 21 Python
Python操作MySQL数据库实例详解【安装、连接、增删改查等】
Jan 17 Python
Python tkinter和exe打包的方法
Feb 05 Python
python实现udp传输图片功能
Mar 20 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
Jun 08 Python
浅谈keras中的后端backend及其相关函数(K.prod,K.cast)
Jun 29 Python
Python常用外部指令执行代码实例
Nov 05 Python
python中的getter与setter你了解吗
Mar 24 Python
python识别文字(基于tesseract)代码实例
Aug 24 #Python
python图片二值化提高识别率代码实例
Aug 24 #Python
关于Python形参打包与解包小技巧分享
Aug 24 #Python
python-序列解包(对可迭代元素的快速取值方法)
Aug 24 #Python
对python中的装包与解包实例详解
Aug 24 #Python
Python3进制之间的转换代码实例
Aug 24 #Python
Python实现朴素贝叶斯的学习与分类过程解析
Aug 24 #Python
You might like
用PHP+java实现自动新闻滚动窗口
2006/10/09 PHP
第三节--定义一个类
2006/11/16 PHP
php中变量及部分适用方法
2008/03/27 PHP
PHP 无限级分类
2017/05/04 PHP
PHP编程实现阳历转换为阴历的方法实例
2017/08/08 PHP
php-app开发接口加密详解
2018/04/18 PHP
IE图片缓存document.execCommand(&quot;BackgroundImageCache&quot;,false,true)
2011/03/01 Javascript
jQuery ajax 路由和过滤器使用说明
2011/08/02 Javascript
jQuery布局插件UI Layout简介及使用方法
2013/04/03 Javascript
javascript消除window.close()的提示窗口
2015/05/20 Javascript
全面解析Bootstrap中tooltip、popover的使用方法
2016/06/13 Javascript
bootstrap table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)代码分享
2017/01/24 Javascript
AngularJS实现select的ng-options功能示例
2017/07/12 Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
2018/01/02 Javascript
angularJs 表格添加删除修改查询方法
2018/02/27 Javascript
独立部署小程序基于nodejs的服务器过程详解
2019/06/24 NodeJs
使用vue打包进行云服务器上传的问题
2020/03/02 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
2020/09/24 Javascript
[01:06:54]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第一场 1月24日
2021/03/11 DOTA
以Flask为例讲解Python的框架的使用方法
2015/04/29 Python
开源Web应用框架Django图文教程
2017/03/09 Python
Python堆排序原理与实现方法详解
2018/05/11 Python
PyQt5的PyQtGraph实践系列3之实时数据更新绘制图形
2019/05/13 Python
Python configparser模块应用过程解析
2020/08/14 Python
通过Python pyecharts输出保存图片代码实例
2020/11/25 Python
英国蜡烛、蜡烛配件和家居香氛购买网站:Yankee Candle
2018/12/12 全球购物
应届生求职推荐信
2013/10/28 职场文书
创业计划书中包含的9个方面
2013/12/26 职场文书
数控机械专业个人的自我评价
2014/01/02 职场文书
幼儿园健康教育方案
2014/06/14 职场文书
教师党的群众路线学习心得体会
2014/11/04 职场文书
个人求职意向书
2015/05/11 职场文书
2015大学生暑期实习报告
2015/07/13 职场文书
《鲸》教学反思
2016/02/23 职场文书
看看如何用Python绘制小米新版天价logo
2021/04/20 Python
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
2021/08/02 MySQL