一、简介
没有接触过脚本或命令的人,使用Python脚本可能不太习惯,在文章Python调用阿里云API接口实现自定义功能【一】——DescribeInstance中介绍了编写Python脚本来使用DescribeInstance接口实现自定义导出功能的实现,本文在此基础上添加了窗口操作功能,使用起来更加直观和方便,界面如下(丑陋了点但是比较稳:随便点不会坏):
二、初始化窗口
1.初始化窗口类
在之前文档中已创建api调用和写入Excel表格的类(Python调用阿里云API接口实现自定义功能【一】——DescribeInstance),这里直接添加创建窗口类,然后直接调用之前类即可。
class Ascm_Gui:
def __init__(self,initWindow):
self.initWindow = initWindow
def pic2py(self,picture_names, py_name):
"""
将图像文件转换为py文件
:param picture_name:
:return:
"""
write_data = []
for picture_name in picture_names:
filename = picture_name.replace('.', '_')
open_pic = open("%s" % picture_name, 'rb')
b64str = base64.b64encode(open_pic.read())
open_pic.close()
# 注意这边b64str一定要加上.decode()
write_data.append('%s = "%s"\n' % (filename, b64str.decode()))
f = open('%s.py' % py_name, 'w+')
for data in write_data:
f.write(data)
f.close()
def set_init_window(self):
#self.initWindow = Tk()
self.nw = 0.1
self.nh = 0.2
self.initWindow.title("政务云平台运维小工具 - Author: 张琼杰")
self.initWindow.geometry('1000x700')
self.initWindow.resizable(0,0)
self.importExcelButton = Button(self.initWindow,text='导出Excel',width='8',bg='lightblue',command=self.WriteToExcel)
self.importExcelButton.place(relx=0.49,rely=self.nh+0.4)
mainmenu = Menu(self.initWindow)
menuFile = Menu(mainmenu)
mainmenu.add_cascade(label='文件',menu=menuFile)
menuFile.add_command(label='退出',command=self.initWindow.destroy)
menuFile.add_command(label='Version: v0.1')
self.initWindow.config(menu=mainmenu)
from memory_image import logo_png as fav
tmp = open('logo1.png', 'wb') # 创建临时的文件
tmp.write(base64.b64decode(fav)) # 把这个图片解码出来,写入文件中
tmp.close()
self.image_file = Image.open('logo1.png')
self.photo = ImageTk.PhotoImage(self.image_file)
self.initWindow.update()
self.bg_width = self.photo.width() / self.initWindow.winfo_width()
self.bg_height = self.photo.height() / self.initWindow.winfo_height()
self.lab = Label(self.initWindow,image=self.photo)
self.lab.place(relx=1-self.bg_width, rely=0, width=300, height=110)
os.remove('logo1.png')
self.OrgLabel = Label(self.initWindow,text='组织')
self.OrgLabel.place(relx=0.1,rely=self.nh,relwidth=0.1)
self.OrgCombobox = Combobox(self.initWindow,textvariable=vars,values=['产互云能力部测试','上海市大数据中心','徐汇区','上海市','云平台应用资源','上海市城运中心','上海市大数据中心','金山区测试','上海市住建委','普陀区','上海市委宣传部','上海市交通委员会','杨浦区','上海市卫生健康委员会信息中心','上海市临港新片区'])
self.OrgCombobox.place(relx=0.18,rely=self.nh,relwidth=0.2)
self.OrgCombobox.set(value='')
self.ProLabel = Label(self.initWindow, text='产品')
self.ProLabel.place(relx=0.1, rely=self.nh+0.1, relwidth=0.1)
self.ProCombobox = Combobox(self.initWindow, textvariable=vars, values=['Ecs'])
self.ProCombobox.place(relx=0.18, rely=self.nh+0.1, relwidth=0.1)
self.ProCombobox.set(value='Ecs')
self.pathLabel = Label(self.initWindow, text='保存路径')
self.pathLabel.place(relx=0.1, rely=self.nh+0.2, relwidth=0.1)
self.defaultPath = tkinter.StringVar(value='D:\\')
self.pathEntry = Entry(self.initWindow, bd=3,textvariable=self.defaultPath)
self.pathEntry.place(relx=0.18, rely=self.nh+0.2, relwidth=0.3)
def WriteToExcel(self):
# 请求数据
if (self.OrgCombobox.get()!='' and self.ProCombobox.get()!='' and self.pathEntry.get()!=''):
try:
ak = ascm_ak().org_ak_select(self.OrgCombobox.get())
product_name = self.ProCombobox.get()
path = self.pathEntry.get()
if (os.path.exists(path)):
megoc = tkinter.messagebox.askokcancel(title='确认操作',
message="确认导出 " + self.OrgCombobox.get() + " 的 " + self.ProCombobox.get() + " 信息到目录 " + self.pathEntry.get() + " 吗?")
if (megoc == True):
if(path[len(path)-1] == '\\'):
file = path + self.OrgCombobox.get() + ".xlsx"
else:
file = path + "\\" +self.OrgCombobox.get() + ".xlsx"
ascm = ConnectToAscm(product_name=product_name, secret_id=ak['secret_id'],
secret_key=ak['secret_key'])
data = ascm.response_ascm()
# 写入Excel
instanceInfo = InstanceInfoToExcel()
instanceInfo.write_excel(file, data)
tkinter.messagebox.showinfo('成功提示!',message='恭喜您,导出成功!')
else:
tkinter.messagebox.showerror(title='错误!', message="保存路径有误,请修改后重试!")
except:
tkinter.messagebox.showerror(title='错误!',message='请检查后重试!')
else:
tkinter.messagebox.showwarning(title='警告!',message="请输入完整信息后再试!")
2.调用方法
def main():
gui = Tk()
gui.update()
agui = Ascm_Gui(gui)
agui.set_init_window()
gui.mainloop()
if __name__ == '__main__':
main()
三、打包程序
将编写的Python文档打包为exe格式文件
1.安装pyinstaller和pywin32包文件
2.创建启动文件
pyi-makespec ascm_tools.spec
启动文件示例:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['ascm_tools.py'],
pathex=['D:\\mydata\\Development\\Python\\MyProjects\\ascm_gov'],
binaries=[],
datas=[('images\\logo.png','images\\logo.png')],
hiddenimports=['queue'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='ascm_tools',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,icon='favicon.ico' )
3.用pyinstaller命令打包
命令格式:
pyinstaller [项目启动文件]
其他参数(按需求选择):
- -F 表示在 dist 文件夹下只生成单个可执行文件(内部包含所有依赖),不加默认会在 dist 生成一大堆依赖文件+可执行文件。
- -D 与 -F 相反用法
- -W 表示去掉控制台窗口,如果你的程序是有界面的,可以不写这个参数。但是测试情况下建议先加上这个参数,因为如果打包不成功,运行时报错信息会在控制台上输出,没有控制台就看不到报错信息。
- -c 表示去掉窗框,使用控制台
- -p 表示自己定义需要加载的类路径,项目中包含多个自建模块的时候需要加上 -p aaa.py -p bbb.py -p ccc.py
- -i 表示可执行文件的图标,后面跟图标的路径
- –hidden-import 后面跟模块名如 queue,用于告诉打包程序某个模块我用不着你不用打包进去
打包完毕后在 dist 文件夹下双击项目启动文件就可以了
示例:
pyinstaller -F -w ascm_tools.spec
有时候加了-w打包后还是有黑屏,可以尝试如下命令:
pyinstaller -F -w -i favicon.ico 24h_Schedule.py --noconsole
pyinstaller报错解决
1.执行打包命令时报错 IndexError: tuple index out of range
- 原因:官网目前的版本是 3.2.1 只支持到 python3.5 ,高版本的 python 尚不支持,
- 解决方法:网上有大神提供了完善版的代码——官网源码里有 https://github.com/pyinstaller/pyinstaller 替换你 python 目录下的 \Lib\site-packages\PyInstaller 即可 这样就支持python3.6了 不过是开发版,可能还不完善。
作者建议最好还是用虚拟环境下的 python3.5 进行打包。
2.执行打包命令时报错 ImportError: No module named ‘queue’
- 原因:尚不清楚
- 解决方法:如果该模块你用不到,可以在执行打包命令时用 –hidden-import 不打包进去。如果程序中需要该模块,在主文件最上面写上 improt queue
3.打包命令执行成功,但双击可执行程序弹出报错窗口failed to excute script xxx
- 原因:打包时内部缺少了某个依赖,这时需要看看控制台打印了什么报错信息,打包时加了 -w 参数的请再打包一次记得去掉 -w
- 现象:基本都是在控制台上发现报错 No module named ‘xxxxx’,如 No module named ‘queue’ 或者 ModuleNotFoundError: No module named ‘PyQt5.sip’
- 解决方法:同2,如果该模块你用不到,可以在执行打包命令时用 –hidden-import 不打包进去。如果程序中需要该模块,在主文件最上面写上 improt xxxxx。如 import queue 或 import PyQt5.sip
评论前必须登录!
注册