python文件打包成exe可执行文件: 以game2048.py脚本为例,实现打包生成可执行文件。
本文介绍将python文件打包成exe可执行文件的方法。
关键库: 提示:pyinstaller安装,使用实践。
1、 安装pyinstaller
anaconda大环境下安装运行:conda install pyinstaller
没有conda就在命令行中运行:pip install pyinstaller
【python编程高阶|python文件打包成exe】2、 打包python文件实例
将编写的2048游戏程序脚本保存在game2048.py中;
把它打包成exe需要在同一文件夹中打开命令行并输入:
pyinstaller -F ./game2048.py
回车后运行,如果一切顺利,文件夹中会多出一个后缀为spec的文件,以及两个名为dist和build的文件夹。
打开dist,可以找到game2048.exe,这就是生成的可执行文件。
3、pyinstaller的其他的选项,参数:
-i: 后接图标文件名,表示用自定义图标生成exe程序
-w: 生成的exe程序不带窗口执行
如果想只运行tkinter 页面,去掉dos窗口需要在打包的时候 加上 -w 参数
eg. pyinstaller -F calc.py -w
注意:
- pyinstaller需安装在脚本所依赖环境env里,或者打包时保证你的脚本运行和所依赖的env一致。比如,用命令行打包有默认python环境,而调试代码用的是另一个环境。
- 生成的exe文件可复制到电脑上的任何地方单独使用。
game2048.py
注意:游戏界面引入了
curses库
,Windows下使用该库的注意事项和安装。# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time: 2021/8/6 15:15
# @Author: Haiyan T
# @Email: 893190391@qq.com
# @File: game2048.py# Begin to show your code!
import curses# 绘制在下的用户界面和漂亮的图形
from random import randrange, choice
from collections import defaultdictletter_codes = [ord(ch) for ch in 'WASDRQwasdrq']# 上左下右,ord函数是把字符转换成对应的数字
actions = ['Up', 'Left', 'Down', 'Right', 'Restart', 'Exit']# 上,左,下,右,重启,退出
actions_dict = dict(zip(letter_codes, actions * 2))# 把字母与动作对应起来。 zip是把元组中的值对应起来。
# print(actions_dict)def get_user_action(keyboard):
char = "N"# char的初始值为N
while char not in actions_dict:
char = keyboard.getch()
return actions_dict[char]# 阻塞+循环,直到获得用户有效输入才返回对应行为# 行列转置
def transpose(field):
return [list(row) for row in zip(*field)]# zip函数里边加*号,是把行变列,列变行。# 列表前后颠倒
def invert(field):
return [row[::-1] for row in field]# 创建棋盘
class GameField(object):
def __init__(self, height=4, width=4, win=2048):
self.height = height# 高
self.width = width# 宽
self.win_value = https://www.it610.com/article/win# 过关分数
self.score = 0# 当前分数
self.highscore = 0# 最高分
self.reset()# 重置棋盘def reset(self):# 定义一个reset函数
if self.score> self.highscore:# 如果当前分数大于最高分,那么把当前分数赋值给最高分
self.highscore = self.score
self.score = 0# 当前分数恢复到0分
self.field = [[0 for i in range(self.width)] for j in range(self.height)]# 横纵坐标恢复到(0,0)
self.spawn()# 调用spawn这个函数
self.spawn()def move(self, direction):# 定义move函数
def move_row_left(row):# 向左移
def tighten(row):# squeese non-zero elements together 把零散的非零单元挤到一块
new_row = [i for i in row if i != 0]# 如果i不等于零,把他们赋值到new_row这个元组中
new_row += [0 for i in range(len(row) - len(new_row))]# 其余位置用0补充
return new_row# 返回这个元组def merge(row):# 定义merge函数,用来合并单元
pair = False# pair初始值为假
new_row = []# new_row初始值为空
for i in range(len(row)):# 让i在格子里循环
if pair:# 如果pair为真
new_row.append(2 * row[i])# 那么把把row【i】的值乘以2,追加到new_row后边
self.score += 2 * row[i]# 并且得分为row【i】的值乘以2
pair = False# pair重新赋值为假
else:# 如果pair为真
if i + 1 < len(row) and row[i] == row[i + 1]:# 如果i+1还没到边界,并且此时的row【i】=row【i+1】
pair = True# 那么pair为真
new_row.append(0)# new_row后追加零
else:
new_row.append(row[i])# 否则追加row【i】
assert len(new_row) == len(row)# 提醒两者长度一致
return new_row
return tighten(merge(tighten(row)))# 反复合并,知道不能合并为止moves = {}
moves['Left'] = lambda field:\
[move_row_left(row) for row in field]# 做移动
moves['Right'] = lambda field:\
invert(moves['Left'](invert(field)))# invert是逆转
moves['Up']= lambda field:\
transpose(moves['Left'](transpose(field)))# transpose是转置
moves['Down']= lambda field:\
transpose(moves['Right'](transpose(field)))if direction in moves:
if self.move_is_possible(direction):# 如果移动方向在四个方向上,
self.field = moves[direction](self.field)# 那么调用moves函数
self.spawn()# 产生随机数
return True
else:
return Falsedef is_win(self):
return any(any(i >= self.win_value for i in row) for row in self.field)def is_gameover(self):
return not any(self.move_is_possible(move) for move in actions)def draw(self, screen):
help_string1 = '(W)Up (S)Down (A)Left (D)Right'
help_string2 = '(R)Restart (Q)Exit'
gameover_string = 'GAME OVER'
win_string = 'YOU WIN!'
def cast(string):
screen.addstr(string + '\n')def draw_hor_separator():
line = '+' + ('+------' * self.width + '+')[1:]
separator = defaultdict(lambda: line)
if not hasattr(draw_hor_separator, "counter"):
draw_hor_separator.counter = 0
cast(separator[draw_hor_separator.counter])
draw_hor_separator.counter += 1def draw_row(row):
cast(''.join('|{: ^5} '.format(num) if num > 0 else '|' for num in row) + '|')screen.clear()
cast('SCORE: ' + str(self.score))
if 0 != self.highscore:
cast('HGHSCORE: ' + str(self.highscore))
for row in self.field:
draw_hor_separator()
draw_row(row)
draw_hor_separator()
if self.is_win():
cast(win_string)
else:
if self.is_gameover():
cast(gameover_string)
else:
cast(help_string1)
cast(help_string2)def spawn(self):
new_element = 4 if randrange(100) > 89 else 2
(i, j) = choice([(i, j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])
self.field[i][j] = new_elementdef move_is_possible(self, direction):
def row_is_left_movable(row):
def change(i): # true if there'll be change in i-th tile
if row[i] == 0 and row[i + 1] != 0:# Move
return True
if row[i] != 0 and row[i + 1] == row[i]:# Merge
return True
return False
return any(change(i) for i in range(len(row) - 1))check = {}
check['Left']= lambda field:\
any(row_is_left_movable(row) for row in field)check['Right'] = lambda field:\
check['Left'](invert(field))check['Up']= lambda field:\
check['Left'](transpose(field))check['Down']= lambda field:\
check['Right'](transpose(field))if direction in check:
return check[direction](self.field)
else:
return Falsedef main(stdscr):
def init():
# 重置游戏棋盘
game_field.reset()
return 'Game'def not_game(state):
# 画出 GameOver 或者 Win 的界面
game_field.draw(stdscr)
# 读取用户输入得到action,判断是重启游戏还是结束游戏
action = get_user_action(stdscr)
responses = defaultdict(lambda: state)# 默认是当前状态,没有行为就会一直在当前界面循环
responses['Restart'], responses['Exit'] = 'Init', 'Exit'# 对应不同的行为转换到不同的状态
return responses[action]def game():
# 画出当前棋盘状态
game_field.draw(stdscr)
# 读取用户输入得到action
action = get_user_action(stdscr)if action == 'Restart':
return 'Init'
if action == 'Exit':
return 'Exit'
if game_field.move(action):# move successful
if game_field.is_win():
return 'Win'
if game_field.is_gameover():
return 'Gameover'
return 'Game'state_actions = {
'Init': init,
'Win': lambda: not_game('Win'),
'Gameover': lambda: not_game('Gameover'),
'Game': game
}curses.use_default_colors()
game_field = GameField(win=2048)state = 'Init'# 状态机开始循环
while state != 'Exit':
state = state_actions[state]()curses.wrapper(main)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
anaconda prompt下运行打包:
(DeepLearningSlideCaptcha) C:\Users\Administrator>pyinstaller -F E:\structure_learning\0304t\2048\game2048.py
- (DeepLearningSlideCaptcha) 环境,可使用
activate
切换。 - pyinstaller -F E:\structure_learning\0304t\2048\game2048.py 命令。
- 结果
......
7280 INFO: checking EXE
7281 INFO: Building EXE because EXE-00.toc is non existent
7281 INFO: Building EXE from EXE-00.toc
7281 INFO: Appending archive to EXE C:\Users\Administrator\dist\game2048.exe
7286 INFO: Building EXE from EXE-00.toc completed successfully.
123456
测试:
- 直接打包
文章图片
双击运行
文章图片
\2. 带图标打包
pyinstaller -F -i 图标地址 脚本地址
回车,打包完成
pyinstaller -F -i E:\TanhaiyanLearn\structure_learning\0304t\2048\2048.icoE:\TanhaiyanLearn\structure_learning\0304t\2048\game2048.pyE:\TanhaiyanLearn\structure_learning\0304t\2048\2048.icoE:\TanhaiyanLearn\structure_learning\0304t\2048\game2048.py
1
文章图片
文章图片
文章图片
推荐阅读
- python编程高阶|用Python写一个计算器
- Python全能工程师2022版完结含文档源码
- 目标检测|目标检测损失函数
- python|利用Python制作证件照
- Python|Python 证件照换背景色(蓝底->白底,蓝底->红底)!
- Digital|图像梯度(Image gradient)
- 计算机视觉|图像形态学操作
- python|他来了!性能吊打 Node.js 和 Deno 的新一代 javaScript 运行时!
- 目标检测|YOLOv5-6.1添加注意力机制(SE、CBAM、ECA、CA)