使用Pyinstaller

时间:2018-03-08 04:30:14

标签: python segmentation-fault pygame pyinstaller

所以我在python中的pygame脚本运行完美,所以我决定尝试捆绑程序,以便使用Pyinstaller分发它。我按照指示编译并运行Pyinstaller:

sudo pip install pyinstaller
pyinstaller Loop.py

工作得很好。然后我运行生成的可执行文件以查看它的运行情况:

cd /dist/Loop/
./Loop

结果是:

Fatal Python error: (pygame parachute) Segmentation Fault
Aborted (core dumped)

似乎没有执行一行Loop.py,因为导入包后的第一行是打开一个新窗口(没有发生)。通过一点谷歌搜索,似乎唯一推荐的解决方案是调试代码以找到分段发生的位置。但是,这没有任何意义,因为代码本身完全正常,它只在使用pyinstaller之后才这样做。我甚至在与Loop可执行文件相同的目录中输入了一个python shell,并验证了导入pygame没有问题。

无论如何,我只是想找到一种捆绑python项目的方法。当然,如果您知道捆绑python项目以进行分发的更好方法(在Ubuntu 16上使用Python 2.7),我很乐意查看它:)

修改

我创建了一个尽可能简化的代码版本,以便专注于主要问题(当然也可以证明问题是可重现的)。这是主程序(Loop.py):

from Car import*

vehicle = Car()


def display_all(main_surface, display_list):
    main_surface.fill((0, 100, 100))
    for element in display_list:
        element.display(main_surface)


def update_all(update_list):
    for element in update_list:
        element.update()


running = True
while running:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            None

    key = pygame.key.get_pressed()

    to_update = [vehicle]
    to_display = [vehicle]

    update_all(to_update)
    display_all(main_s, to_display)
    pygame.display.flip()

这是Car.py

from Startup import*


class Car:
    def __init__(self):
        self.body = pygame.image.load("Images//Body//Grey.png")
        self.wheels = pygame.image.load("Images//Wheels//Black.png")
        self.rect = self.body.get_rect()
        self.rect.x = width/2
        self.rect.y = height/2
        self.rect.center = self.rect.x, self.rect.y
        self.angle = 0
        self.move_x = 0
        self.move_y = 0

    def display(self, main_surface):
        temp_image = pygame.transform.rotate(self.body, self.angle)
        main_surface.blit(temp_image, (self.rect.x, self.rect.y))
        temp_image = pygame.transform.rotate(self.wheels, self.angle)
        main_surface.blit(temp_image, (self.rect.x, self.rect.y))

    def update(self):
        self.move_x = 0
        self.move_y = 0

这是Startup.py

import pygame
import math
pygame.font.init()

clock = pygame.time.Clock()
font = pygame.font.SysFont("", 20)

pygame.init()
width = 1000
height = 600
main_s = pygame.display.set_mode((width, height))

编辑(再次)

我刚刚按照评论中的建议尝试了py2app,但似乎无效。正如the only documentation中所见,我可以找到,目的是在MacOS上运行。如上所述,我使用的是Ubuntu 16,这就是我编写的架构。当我完成上面链接的教程时,我没有任何复杂情况,并继续执行文件:

./dist/Loop.app/Contents/MacOS/Loop

我很快就收到了错误:

bash: cannot execute binary file: Exec format error

这似乎表明它不适合我的电脑。

你知道是否有适用于Ubuntu的版本?或者如果有其他解决方案?

谢谢, 森

1 个答案:

答案 0 :(得分:1)

感谢您提供一个合适的例子,它帮助我确定了罪魁祸首:

font = pygame.font.SysFont("", 20)

如果禁用该行,您应该能够构建并运行可执行文件。这很容易测试,因为您的示例中未使用font

如果您将名称更改为Arial可能提供的内容,或者将列表包含为documentation states,则搜索不存在的字体似乎存在问题。或者您可以指定可用字体,例如pygame.font.get_fonts()[0]

这是一个修改过的示例,可以将汽车移向您点击鼠标的位置:

import pygame
import math

pygame.init()
pygame.font.init()
all_fonts = pygame.font.get_fonts()
print(all_fonts)
font = pygame.font.SysFont(all_fonts[0], 20) # just use the first font.
#font = pygame.font.SysFont("Arial, couriernewm", 20)
clock = pygame.time.Clock()

width = 1000
height = 600
main_s = pygame.display.set_mode((width, height))

class Car(pygame.sprite.Sprite):
    """Sprite with self drawn images"""
    def __init__(self, speed=5):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((40,30)).convert_alpha()  # sprites need an 'image'
        self.image.fill((0,0,0,0)) # make transparent
        pygame.draw.rect(self.image, (111,111,111), (0,5, 40, 15)) # draw the body
        for center in [(5,5), (35,5), (5,20), (35, 20)]:  # draw four wheels
            pygame.draw.circle(self.image, (0,0,0), center, 5)
        self.rect = self.image.get_rect()
        self.rect.x = width/2
        self.rect.y = height/2
        self.rect.center = self.rect.x, self.rect.y
        self.angle = 0
        self.move_x = 0
        self.move_y = 0
        self.speed = speed
        self.destination = self.rect.center

    def update(self, pos=None):
        if pos:
            #set new destination
            self.destination = pos
        else:
        # move towards destination at speed
            xd = self.destination[0] - self.rect.center[0]
            if xd < 0:
                xd = max(xd, -self.speed)
            else:
                xd = min(xd, self.speed)
            yd = self.destination[1] - self.rect.center[1]
            if yd < 0:
               yd = max(yd, -self.speed)
            else:
                yd = min(yd, self.speed)
            self.rect.center = (self.rect.center[0] + xd, self.rect.center[1] + yd)


# create a sprite group to store cars
slow_car = Car()
vehicles = pygame.sprite.Group(slow_car)

running = True
#main loop
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            pass
        elif event.type == pygame.MOUSEBUTTONDOWN:
            # move to position
            vehicles.update(event.pos)
    # update sprites
    vehicles.update()

    # clear surface
    main_s.fill((0, 100, 100))

    #draw sprites
    vehicles.draw(main_s)

    # update display
    pygame.display.update()
    clock.tick(10)
pygame.quit()

注意:不幸的是,这不是在Mac上运行,因此我无法保证它能够正常运行。启动可执行文件时,我确实看到了应用程序失败。