exe 编译的 Kivy 程序访问图像的问题

Posted

技术标签:

【中文标题】exe 编译的 Kivy 程序访问图像的问题【英文标题】:Issues with exe compiled Kivy programs accessing images 【发布时间】:2016-10-04 08:20:43 【问题描述】:

所以我创建了一个简单的程序,用自定义图像替换滑块光标背景,并尝试使用PyInstaller 使用-F 参数对其进行编译(将其编译为单个exe)。编译成功,但是当我尝试执行它时,它无法加载图像并显示以下错误日志:

[WARNING           ] [Image       ] Unable to load image <rogue.jpg>
 Traceback (most recent call last):
   File "site-packages\kivy\lang\builder.py", line 822, in _build_canvas
   File "kivy\graphics\instructions.pyx", line 362, in kivy.graphics.instruction
s.VertexInstruction.source.__set__ (kivy\graphics\instructions.c:7177)
   File "kivy\graphics\context_instructions.pyx", line 381, in kivy.graphics.con
text_instructions.BindTexture.source.__set__ (kivy\graphics\context_instructions
.c:7309)
   File "site-packages\kivy\core\image\__init__.py", line 528, in __init__
   File "site-packages\kivy\core\image\__init__.py", line 716, in _set_filename
   File "site-packages\kivy\core\image\__init__.py", line 432, in load
   File "site-packages\kivy\core\image\__init__.py", line 200, in __init__

   File "site-packages\kivy\core\image\img_sdl2.py", line 41, in load
 Exception: SDL2: Unable to load image

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "untitled-1.py", line 21, in <module>
     TestApp().run()
   File "site-packages\kivy\app.py", line 802, in run
   File "untitled-1.py", line 19, in build
     return MySlider()
   File "site-packages\kivy\uix\widget.py", line 321, in __init__
   File "site-packages\kivy\lang\builder.py", line 447, in apply
   File "site-packages\kivy\lang\builder.py", line 502, in _apply_rule
   File "site-packages\kivy\lang\builder.py", line 827, in _build_canvas
 kivy.lang.builder.BuilderException: Parser: File "<inline>", line 7:
 ...
       5:            pos: (self.value_pos[0] - sp(16), self.center_y - sp(17)) i
f self.orientation == 'horizontal' else (self.center_x - (16), self.value_pos[1]
 - sp(16))
       6:            size: (sp(32), sp(32))
 >>    7:            source: 'rogue.jpg'
 ...
 Exception: SDL2: Unable to load image
   File "site-packages\kivy\lang\builder.py", line 822, in _build_canvas
   File "kivy\graphics\instructions.pyx", line 362, in kivy.graphics.instruction
s.VertexInstruction.source.__set__ (kivy\graphics\instructions.c:7177)
   File "kivy\graphics\context_instructions.pyx", line 381, in kivy.graphics.con
text_instructions.BindTexture.source.__set__ (kivy\graphics\context_instructions
.c:7309)
   File "site-packages\kivy\core\image\__init__.py", line 528, in __init__
   File "site-packages\kivy\core\image\__init__.py", line 716, in _set_filename
   File "site-packages\kivy\core\image\__init__.py", line 432, in load
   File "site-packages\kivy\core\image\__init__.py", line 200, in __init__
   File "site-packages\kivy\core\image\img_sdl2.py", line 41, in load

Failed to execute script untitled-1

我发现有趣的是,如果我从 cwd 中删除 rogue.jpg 图像,程序运行得很好。它只是给了我一个空白的白色矩形。 但是为什么第一种情况会出错而第二种情况没有呢?我该如何预防?

这里是image和源代码:

from kivy.app import App
from kivy.uix.slider import Slider
from kivy.lang import Builder

Builder.load_string('''
<Slider>:
    canvas:
        Rectangle:
            pos: (self.value_pos[0] - sp(16), self.center_y - sp(17)) if self.orientation == 'horizontal' else (self.center_x - (16), self.value_pos[1] - sp(16))
            size: (sp(32), sp(32))
            source: 'rogue.jpg'
''')

class MySlider(Slider):
    pass

class TestApp(App):
    def build(self):
        return MySlider()

TestApp().run()

Python 3.4、Kivy v1.9.2-dev0、Windows 编译的 .exe 文件可以在here找到。

【问题讨论】:

所以构建器放弃了,也许是因为在画布的矩形(在提供给加载器的字符串内)为 pos 和 size 计算的值? x、y、宽度和高度的值是多少(我猜)?有效的整数/浮点数? @Dilettant 代码工作正常。如果我运行 .py 文件,一切正常。因此,值是有效的。编译后的文件试图访问图片有问题 尝试检查路径和工作目录,脚本是否可以找到文件。 @EugeneLisitsky 位于同一目录下的.py 脚本能够成功定位到文件 尝试从脚本打印cwd - 可能会将其更改为某个内部文件夹吗?环境中有哪些文件夹? kivy.org/docs/guide/environment.html 【参考方案1】:

无论是什么,您的图像源代码中都缺少一个“sp” :-)

代替:

pos: (self.value_pos[0] - sp(16), self.center_y - sp(17)) if self.orientation == 'horizontal' else (self.center_x - (16), self.value_pos[1] - sp(16))

试试这个:

pos: (self.value_pos[0] - sp(16), self.center_y - sp(17)) if self.orientation == 'horizontal' else (self.center_x - sp(16), self.value_pos[1] - sp(16))

或“反斜杠”格式(至少在这里不要滚动太右才能看到):

pos: (self.value_pos[0] - sp(16), self.center_y - sp(17))\
    if self.orientation == 'horizontal'\
    else (self.center_x - sp(16), self.value_pos[1] - sp(16))

【讨论】:

这很有趣。我从 Kivy 的 GitHub 存储库中复制了画布描述,看起来就是他们,谁错过了它。我会举报的 另外,它似乎无法解决问题 我对 kivy 魔法没有经验,所以以下内容可能没有帮助:当 Builder 加载您的字符串时,source 字段值,可以只是一个文件名,还是可以需要一个锚点,即一个特殊的相对路径(取决于“构建器”假设从哪里搜索/解析或绝对路径? 不,路径是相对于cwd(源代码所在位置)的。如果我只运行 .py 代码,代码无需编译即可正常工作

以上是关于exe 编译的 Kivy 程序访问图像的问题的主要内容,如果未能解决你的问题,请参考以下文章

PyInstaller 编译的 Kivy 应用程序不起作用

SDL2 错误:使用 pyinstaller 冻结 kivy 应用程序时“无法加载图像 <default.png>”

Android kivy 在哪里放置应用程序文件(ini、图像数据库等)

使用 pyinstaller 为 kivy 应用程序生成单个 exe

将 kivy 应用程序打包到一个 exe 中

Kivy/KivyMD 应用程序在 venv 环境中运行良好,但在 exe 文件中崩溃