鱼的七秒记忆 发表于 2021-1-28 18:36:04

怎样将py文件和资源文件打包成一个exe

怎样将py文件和资源文件打包成一个exe?

hrp 发表于 2021-1-28 18:36:05

本帖最后由 hrp 于 2021-1-28 23:34 编辑

打包成单exe文件并把资源文件添加到exe文件中,你的源代码需要进行修改。

首先你的源代码中要确定当前目录的起始路径,因为打包成单exe文件后,当前目录并不是exe文件所在的文件夹。

import os, sys
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    cur_dir = sys._MEIPASS
else:
    cur_dir = os.path.dirname(os.path.abspath(__file__))

以后代码中读取任何资源文件时,都应以cur_dir为起始。
例如你的程序要读取与py文件在同一文件夹下的mm.jpeg:
# mm.jpeg文件的路径应该是
jpeg_path = os.path.join(cur_dir, 'mm.jpeg')
# 读取mm.jpeg时应按jpeg_path读取

然后使用3#推荐的工具,把你的资源文件添加到"非源代码资源文件"中,打包后就可以运行了。


如果打包成单exe但资源文件是放在与打包后的exe文件相同目录下,
那上面说的起始路径用
cur_dir = os.path.dirname(os.path.abspath(__file__))
即可。


如果打包成单目录,那你的源代码基本上不需要修改,直接添加该添加的资源文件到"非源代码资源文件"中,打包后即可运行。

liaozuhen 发表于 2021-1-28 19:11:37

https://fishc.com.cn/forum.php?mod=viewthread&tid=188498&highlight=exe

liaozuhen 发表于 2021-1-28 19:15:50


青出于蓝 发表于 2021-1-28 20:20:14

https://blog.csdn.net/douzhenwen/article/details/78886244

鱼的七秒记忆 发表于 2021-1-28 21:11:19

liaozuhen 发表于 2021-1-28 19:11
https://fishc.com.cn/forum.php?mod=viewthread&tid=188498&highlight=exe

为啥我的python环境选择不了

鱼的七秒记忆 发表于 2021-1-29 12:15:57

hrp 发表于 2021-1-28 21:42
打包成单exe文件并把资源文件添加到exe文件中,你的源代码需要进行修改。

首先你的源代码中要确定当前目 ...

恕我新手,大神指导一下

鱼的七秒记忆 发表于 2021-1-29 12:17:23

这是我的源码import random
import pygame
import sys

from pygame.locals import *
pygame.mixer.init()
pygame.mixer.music.load("music.mp3")

snake_speed = 5# 速度
windows_width = 800
windows_height = 600 #大小
cell_size = 20       #贪方块大小

map_width = int(windows_width / cell_size)
map_height = int(windows_height / cell_size)

# 颜色定义
white = (255, 255, 255)
black = (0, 0, 0)
gray = (230, 230, 230)
dark_gray = (40, 40, 40)
DARKGreen = (0, 155, 0)
Green = (0, 255, 0)
Red = (255, 0, 0)
blue = (0, 0, 255)
dark_blue =(0,0, 139)

BG_COLOR = black #背景色

# 方向
UP = 4
DOWN = 3
LEFT = 2
RIGHT = 1

HEAD = 0 #贪吃蛇

#主函数
def main():
    pygame.init() # 模块初始化
    snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象
    screen = pygame.display.set_mode((windows_width, windows_height)) #
    screen.fill(white)

    pygame.display.set_caption("蟒蛇修仙") #设置标题
    show_start_info(screen)               #欢迎信息
    while True:
      running_game(screen, snake_speed_clock)
      show_gameover_info(screen)

#游戏运行主体
def running_game(screen,snake_speed_clock):
    startx = random.randint(3, map_width - 8) #开始位置
    starty = random.randint(3, map_height - 8)
    snake_coords = [{'x': startx, 'y': starty},#初始贪吃蛇
                  {'x': startx - 1, 'y': starty},
                  {'x': startx - 2, 'y': starty}]

    direction = RIGHT       #开始时向右移动

    food = get_random_location()   #实物随机位置

    while True:
      for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:
                if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
                  direction = LEFT
                elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
                  direction = RIGHT
                elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
                  direction = UP
                elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
                  direction = DOWN
                elif event.key == K_ESCAPE:
                  terminate()

      move_snake(direction, snake_coords) #移动蛇

      ret = snake_is_alive(snake_coords)
      if not ret:
            break # 游戏结束
      snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物

      screen.fill(BG_COLOR)
      #draw_grid(screen)
      draw_snake(screen, snake_coords)
      draw_food(screen, food)
      draw_score(screen, len(snake_coords) - 3)
      pygame.display.update()
      snake_speed_clock.tick(snake_speed) #控制fps
#将食物画出来
def draw_food(screen, food):
    x = food['x'] * cell_size
    y = food['y'] * cell_size
    appleRect = pygame.Rect(x, y, cell_size, cell_size)
    pygame.draw.rect(screen, Red, appleRect)
#将贪吃蛇画出来
def draw_snake(screen, snake_coords):
    for coord in snake_coords:
      x = coord['x'] * cell_size
      y = coord['y'] * cell_size
      wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
      pygame.draw.rect(screen, dark_blue, wormSegmentRect)
      wormInnerSegmentRect = pygame.Rect(                #蛇身子里面的第二层亮绿色
            x + 4, y + 4, cell_size - 8, cell_size - 8)
      pygame.draw.rect(screen, blue, wormInnerSegmentRect)
#画网格(可选)
def draw_grid(screen):
    for x in range(0, windows_width, cell_size):# draw 水平 lines
      pygame.draw.line(screen, dark_gray, (x, 0), (x, windows_height))
    for y in range(0, windows_height, cell_size):# draw 垂直 lines
      pygame.draw.line(screen, dark_gray, (0, y), (windows_width, y))
#移动贪吃蛇
def move_snake(direction, snake_coords):
    if direction == UP:
      newHead = {'x': snake_coords['x'], 'y': snake_coords['y'] - 1}
    elif direction == DOWN:
      newHead = {'x': snake_coords['x'], 'y': snake_coords['y'] + 1}
    elif direction == LEFT:
      newHead = {'x': snake_coords['x'] - 1, 'y': snake_coords['y']}
    elif direction == RIGHT:
      newHead = {'x': snake_coords['x'] + 1, 'y': snake_coords['y']}

    snake_coords.insert(0, newHead)
#判断蛇死了没
def snake_is_alive(snake_coords):
    tag = True
    if snake_coords['x'] == -1 or snake_coords['x'] == map_width or snake_coords['y'] == -1 or \
            snake_coords['y'] == map_height:
      tag = False # 蛇碰壁啦
    for snake_body in snake_coords:
      if snake_body['x'] == snake_coords['x'] and snake_body['y'] == snake_coords['y']:
            tag = False # 蛇碰到自己身体啦
    return tag
#判断贪吃蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):#如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。
    if snake_coords['x'] == food['x'] and snake_coords['y'] == food['y']:
      food['x'] = random.randint(0, map_width - 1)
      food['y'] = random.randint(0, map_height - 1) # 实物位置重新设置
    else:
      del snake_coords[-1]# 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
#食物随机生成
def get_random_location():
    return {'x': random.randint(0, map_width - 1), 'y': random.randint(0, map_height - 1)}
#开始信息显示
def show_start_info(screen):
    if pygame.mixer.music.get_busy() == False:
      pygame.mixer.music.play()
    font = pygame.font.Font('myfont.ttf', 40)
    tip = font.render('按任意键开始游戏', True, (65, 105, 225))
    gamestart = pygame.image.load('ks.png')
    screen.blit(gamestart, (140, 30))
    screen.blit(tip, (240, 550))
    pygame.display.update()

    while True:#键盘监听事件
      for event in pygame.event.get():# event handling loop
            if event.type == QUIT:
                terminate()   #终止程序
            elif event.type == KEYDOWN:
                if (event.key == K_ESCAPE):#终止程序
                  terminate() #终止程序
                else:
                  return #结束此函数, 开始游戏
#游戏结束信息显示
def show_gameover_info(screen):
    if pygame.mixer.music.get_busy() == False:
      pygame.mixer.music.play()
    font = pygame.font.Font('myfont.ttf', 40)
    tip = font.render('按Q或者ESC退出, 按任意键重新开始', True, (65, 105, 225))
    gamestart = pygame.image.load('sw.png')
    screen.blit(gamestart, (60, 0))
    screen.blit(tip, (80, 300))
    pygame.display.update()

    while True:#键盘监听事件
      for event in pygame.event.get():# event handling loop
            if event.type == QUIT:
                terminate()   #终止程序
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE or event.key == K_q:#终止程序
                  terminate() #终止程序
                else:
                  return #结束此函数, 重新开始游戏
#画成绩
def draw_score(screen,score):
    font = pygame.font.Font('myfont.ttf', 30)
    scoreSurf = font.render('得分: %s' % score, True, Green)
    scoreRect = scoreSurf.get_rect()
    scoreRect.topleft = (windows_width - 120, 10)
    screen.blit(scoreSurf, scoreRect)
#程序终止
def terminate():
    pygame.quit()
    sys.exit()


main()

liaozuhen 发表于 2021-1-29 12:57:53

鱼的七秒记忆 发表于 2021-1-28 21:11
为啥我的python环境选择不了



然后就可以选择python环境了

鱼的七秒记忆 发表于 2021-1-29 13:05:24

liaozuhen 发表于 2021-1-29 12:57
然后就可以选择python环境了

我生成出来是spec和pyc文件

鱼的七秒记忆 发表于 2021-1-29 13:14:23

没有exe

鱼的七秒记忆 发表于 2021-1-29 13:25:33

hrp大佬说要加代码我不知道加在哪

鱼的七秒记忆 发表于 2021-1-29 13:26:05

鱼的七秒记忆 发表于 2021-1-29 12:17
这是我的源码

源码如上

hrp 发表于 2021-1-29 13:45:58

鱼的七秒记忆 发表于 2021-1-29 13:14
没有exe

如果没有修改生成文件的储存位置,并且提示打包完成,那exe文件就在与py文件同位置的dist文件夹里。

hrp 发表于 2021-1-29 13:48:08

本帖最后由 hrp 于 2021-1-29 13:51 编辑

鱼的七秒记忆 发表于 2021-1-29 12:17
这是我的源码

import random
import pygame
import sys, os

def abs_path(rel):
    if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
      # 如果已打包则当前目录是以下路径
      cur_dir = sys._MEIPASS
    else:
      # 如果没有打包,则当前目录是py文件所在目录
      cur_dir = os.path.dirname(os.path.abspath(__file__))
    # 返回文件rel的绝对路径
    return os.path.join(cur_dir, rel)

from pygame.locals import *
pygame.mixer.init()
# 调用 abs_path 函数,读取其他资源文件同理
pygame.mixer.music.load(abs_path("music.mp3"))

snake_speed = 5# 速度
windows_width = 800
windows_height = 600 #大小
cell_size = 20       #贪方块大小

map_width = int(windows_width / cell_size)
map_height = int(windows_height / cell_size)

# 颜色定义
white = (255, 255, 255)
black = (0, 0, 0)
gray = (230, 230, 230)
dark_gray = (40, 40, 40)
DARKGreen = (0, 155, 0)
Green = (0, 255, 0)
Red = (255, 0, 0)
blue = (0, 0, 255)
dark_blue =(0,0, 139)

BG_COLOR = black #背景色

# 方向
UP = 4
DOWN = 3
LEFT = 2
RIGHT = 1

HEAD = 0 #贪吃蛇

#主函数
def main():
    pygame.init() # 模块初始化
    snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象
    screen = pygame.display.set_mode((windows_width, windows_height)) #
    screen.fill(white)

    pygame.display.set_caption("蟒蛇修仙") #设置标题
    show_start_info(screen)               #欢迎信息
    while True:
      running_game(screen, snake_speed_clock)
      show_gameover_info(screen)

#游戏运行主体
def running_game(screen,snake_speed_clock):
    startx = random.randint(3, map_width - 8) #开始位置
    starty = random.randint(3, map_height - 8)
    snake_coords = [{'x': startx, 'y': starty},#初始贪吃蛇
                  {'x': startx - 1, 'y': starty},
                  {'x': startx - 2, 'y': starty}]

    direction = RIGHT       #开始时向右移动

    food = get_random_location()   #实物随机位置

    while True:
      for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:
                if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
                  direction = LEFT
                elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
                  direction = RIGHT
                elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
                  direction = UP
                elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
                  direction = DOWN
                elif event.key == K_ESCAPE:
                  terminate()

      move_snake(direction, snake_coords) #移动蛇

      ret = snake_is_alive(snake_coords)
      if not ret:
            break # 游戏结束
      snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物

      screen.fill(BG_COLOR)
      #draw_grid(screen)
      draw_snake(screen, snake_coords)
      draw_food(screen, food)
      draw_score(screen, len(snake_coords) - 3)
      pygame.display.update()
      snake_speed_clock.tick(snake_speed) #控制fps
#将食物画出来
def draw_food(screen, food):
    x = food['x'] * cell_size
    y = food['y'] * cell_size
    appleRect = pygame.Rect(x, y, cell_size, cell_size)
    pygame.draw.rect(screen, Red, appleRect)
#将贪吃蛇画出来
def draw_snake(screen, snake_coords):
    for coord in snake_coords:
      x = coord['x'] * cell_size
      y = coord['y'] * cell_size
      wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
      pygame.draw.rect(screen, dark_blue, wormSegmentRect)
      wormInnerSegmentRect = pygame.Rect(                #蛇身子里面的第二层亮绿色
            x + 4, y + 4, cell_size - 8, cell_size - 8)
      pygame.draw.rect(screen, blue, wormInnerSegmentRect)
#画网格(可选)
def draw_grid(screen):
    for x in range(0, windows_width, cell_size):# draw 水平 lines
      pygame.draw.line(screen, dark_gray, (x, 0), (x, windows_height))
    for y in range(0, windows_height, cell_size):# draw 垂直 lines
      pygame.draw.line(screen, dark_gray, (0, y), (windows_width, y))
#移动贪吃蛇
def move_snake(direction, snake_coords):
    if direction == UP:
      newHead = {'x': snake_coords['x'], 'y': snake_coords['y'] - 1}
    elif direction == DOWN:
      newHead = {'x': snake_coords['x'], 'y': snake_coords['y'] + 1}
    elif direction == LEFT:
      newHead = {'x': snake_coords['x'] - 1, 'y': snake_coords['y']}
    elif direction == RIGHT:
      newHead = {'x': snake_coords['x'] + 1, 'y': snake_coords['y']}

    snake_coords.insert(0, newHead)
#判断蛇死了没
def snake_is_alive(snake_coords):
    tag = True
    if snake_coords['x'] == -1 or snake_coords['x'] == map_width or snake_coords['y'] == -1 or \
            snake_coords['y'] == map_height:
      tag = False # 蛇碰壁啦
    for snake_body in snake_coords:
      if snake_body['x'] == snake_coords['x'] and snake_body['y'] == snake_coords['y']:
            tag = False # 蛇碰到自己身体啦
    return tag
#判断贪吃蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):#如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。
    if snake_coords['x'] == food['x'] and snake_coords['y'] == food['y']:
      food['x'] = random.randint(0, map_width - 1)
      food['y'] = random.randint(0, map_height - 1) # 实物位置重新设置
    else:
      del snake_coords[-1]# 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
#食物随机生成
def get_random_location():
    return {'x': random.randint(0, map_width - 1), 'y': random.randint(0, map_height - 1)}
#开始信息显示
def show_start_info(screen):
    if pygame.mixer.music.get_busy() == False:
      pygame.mixer.music.play()
    font = pygame.font.Font('myfont.ttf', 40)
    tip = font.render('按任意键开始游戏', True, (65, 105, 225))
    gamestart = pygame.image.load('ks.png')
    screen.blit(gamestart, (140, 30))
    screen.blit(tip, (240, 550))
    pygame.display.update()

    while True:#键盘监听事件
      for event in pygame.event.get():# event handling loop
            if event.type == QUIT:
                terminate()   #终止程序
            elif event.type == KEYDOWN:
                if (event.key == K_ESCAPE):#终止程序
                  terminate() #终止程序
                else:
                  return #结束此函数, 开始游戏
#游戏结束信息显示
def show_gameover_info(screen):
    if pygame.mixer.music.get_busy() == False:
      pygame.mixer.music.play()
    font = pygame.font.Font('myfont.ttf', 40)
    tip = font.render('按Q或者ESC退出, 按任意键重新开始', True, (65, 105, 225))
    gamestart = pygame.image.load('sw.png')
    screen.blit(gamestart, (60, 0))
    screen.blit(tip, (80, 300))
    pygame.display.update()

    while True:#键盘监听事件
      for event in pygame.event.get():# event handling loop
            if event.type == QUIT:
                terminate()   #终止程序
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE or event.key == K_q:#终止程序
                  terminate() #终止程序
                else:
                  return #结束此函数, 重新开始游戏
#画成绩
def draw_score(screen,score):
    font = pygame.font.Font('myfont.ttf', 30)
    scoreSurf = font.render('得分: %s' % score, True, Green)
    scoreRect = scoreSurf.get_rect()
    scoreRect.topleft = (windows_width - 120, 10)
    screen.blit(scoreSurf, scoreRect)
#程序终止
def terminate():
    pygame.quit()
    sys.exit()


main()


顺便提一句,mp3格式的音乐,打包后可能完成程序无法运行,有鱼油试过ogg或wav格式的正常(到底是哪个格式我忘了)

鱼的七秒记忆 发表于 2021-1-29 14:50:22

hrp 发表于 2021-1-29 13:48
顺便提一句,mp3格式的音乐,打包后可能完成程序无法运行,有鱼油试过ogg或wav格式的正常(到底是哪 ...

我打包出来运行显示failed to execute script(无法执行脚本)是咋回事

liaozuhen 发表于 2021-1-29 15:04:53

鱼的七秒记忆 发表于 2021-1-29 13:05
我生成出来是spec和pyc文件

hrp 发表于 2021-1-29 15:05:55

鱼的七秒记忆 发表于 2021-1-29 14:50
我打包出来运行显示failed to execute script(无法执行脚本)是咋回事

打包之前能运行吗?
音乐格式转换过没?

liaozuhen 发表于 2021-1-29 15:08:09

建议打包成单目录

liaozuhen 发表于 2021-1-29 15:09:50

鱼的七秒记忆 发表于 2021-1-29 14:50
我打包出来运行显示failed to execute script(无法执行脚本)是咋回事

打包成单目录就可以了吧
页: [1]
查看完整版本: 怎样将py文件和资源文件打包成一个exe