簡體   English   中英

由於 KeyError,Pyinstaller 無法運行 Kivy 應用程序

[英]Pyinstaller is unable to run a Kivy Application due to KeyError

我正在使用 pyinstaller 打包 Kivy 應用程序。 原始應用程序工作正常,但從 dist 文件夾運行時,由於關鍵錯誤而失敗。 具體來說,它啟動了 Kivy 應用程序,但隨后由於密鑰錯誤而立即關閉。

錯誤信息:

 Traceback (most recent call last):
   File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'screen_login'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "cli.py", line 5, in <module>
   File "kivy\app.py", line 949, in run
   File "kivy\app.py", line 919, in _run_prepare
   File "src\__main__.py", line 26, in build
   File "src\__main__.py", line 20, in __init__
   File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

添加了帶有資源路徑 function 的 main.py。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import os
import sys
from kivy.resources import resource_add_path, resource_find


# Import files like
from CheckIn_Application.src.screens.login.login import LoginScreen
from CheckIn_Application.src.screens.checkin.checkin import CheckInScreen


def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)


# Make all stuff modular
class WindowManager(BoxLayout):
    # Class Widgets
    login_widget = LoginScreen()
    check_in_widget = CheckInScreen()

    print(resource_path('maincheckin.kv'))

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # super(WindowManager, self).__init__(**kwargs)

        # Add Widget
        self.ids.screen_login.add_widget(self.login_widget)
        self.ids.screen_checkin.add_widget(self.check_in_widget)


class MainCheckin(App):
    def build(self):
        return WindowManager()


if __name__ == "__main__":
    # Main().run()
    if hasattr(sys, '_MEIPASS'):
        resource_add_path(os.path.join(sys._MEIPASS))
    MainCheckin().run()

以及關聯的.kv 文件

<WindowManager>:
    id: main_window

    ScreenManager:
        id: scrn_mngr_main

        Screen:
            id: screen_login
            name:'screen_login'
        Screen:
            id: screen_checkin
            name:'screen_checkin'

我認為這與 pyinstaller 如何與 .kv 文件交互有關。 當我在原始代碼中將屏幕的 id 更改為字符串(即 id:“screen_login 與 id:screen_login”)時,我可以復制此錯誤。我認為 Kivy 指出不將其元素 id 標識為字符串。

編輯:規格文件:

# -*- mode: python ; coding: utf-8 -*-
import os
import sys

from pathlib import Path
from pylibdmtx import pylibdmtx
from pyzbar import pyzbar

from kivy_deps import sdl2, glew


block_cipher = None


a = Analysis(
             ['cli.py'],
             pathex=['C:/Users/username/PycharmProjects/DBlytics/CheckIn_Application'],
             binaries=[],
             datas=[('C:/Users/username/PycharmProjects/DBlytics/CheckIn_Application/src/maincheckin.kv','.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

# dylibs are not detected because loaded by ctypes.
# binaries accept the TOC format.  Use list comprehension.
a.binaries += TOC([
    (Path(dep._name).name, dep._name, 'BINARY')
    for dep in pylibdmtx.EXTERNAL_DEPENDENCIES + pyzbar.EXTERNAL_DEPENDENCIES
])

# A dependency of libzbar.dylib that PyInstaller does not detect
MISSING_DYLIBS = (
    Path('/usr/local/lib/libjpeg.8.dylib'),
)
a.binaries += TOC([
    (lib.name, str(lib.resolve()), 'BINARY') for lib in MISSING_DYLIBS
])


pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

a.datas += [('maincheckin.kv', 'C:/Users/username/PycharmProjects/DBlytics/CheckIn_Application/src/maincheckin.kv', 'DATA')]

exe = EXE(
          pyz,
          a.scripts,
          # *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
          [],
          exclude_binaries=True,
          name='cli',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )

coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
               strip=False,
               upx=True,
               upx_exclude=[],
               name='cli')

在此方法中將 .kv 文件添加到規范時,我注意到 pyinstaller 將 .kv 文件添加到 dist\cli\ 文件夾而不是 _MEIPASS 臨時文件夾。

問題是我的原始代碼是正確的,但是在我 package 之后,這個錯誤就會被拋出。

你可以和我分享 your.spec 文件嗎? 幾周前我遇到了同樣的問題。 我認為您沒有指定數據源。

My.spec 文件位於:../denul2/ 我的代碼文件 (.py/.kv) 位於:../denul2/project/

看這個: https://imgur.com/a/pWCKPQ1

編輯:嘗試也添加這個: https://imgur.com/a/rGFOMw5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM