无法在exe文件中添加图像和.kv文件

问题描述 投票:0回答:2

当我的应用程序由 pyinstaller 创建的 exe 文件时,它不断显示错误,现在这是我发现的最后一个错误

Traceback (most recent call last):
  File "TestAnalysis.py", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module
  File "kivy\__init__.py", line 319, in <module>
  File "<frozen importlib._bootstrap>", line 568, in module_from_spec
AttributeError: 'NoneType' object has no attribute 'loader'

我想在exe文件中添加所有图像和kivy文件,它应该独立于任何依赖项,以便我可以分发

pyinstaller --onefile -w --add-data="thelab.kv:." --add-data="images (1).jpg:." --add-data="Screenshot (23).png:." --add-data="Screenshot (24).png:." --add-data="Screenshot (25).png:." --add-data="KivyAppData.db:." --add-data="AppIcon.ico:." --icon=AppIcon.ico --hidden-import plyer.platforms.win.filechooser --hidden-import kivy_deps.gstreamer --hidden-import kivy_deps.angle --hidden-import kivy.core.image.img_ffpyplayer --hidden-import kivy.core.text.text_pil TestAnalysis.py

这是我用于将所有文件转换为exe文件的代码,并且所有文件都位于同一文件夹中,因此绝对路径不应该成为问题

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from plyer import filechooser
import csv, sqlite3,random
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
import os, sys
from kivy.resources import resource_add_path

class StudentButton(Button): 
    pass
class MainScreen(Screen):
    s = []
    val = 0
    files = []  
    def file_chooser1(self):
        if App.get_running_app().s_0 == 'invalid input':
            App.get_running_app().s_0 = ''
        file = filechooser.open_file()
        self.files+=file
        App.get_running_app().s_0 += "".join(file).split("\\")[-1] + '\n'

    def Enter(self):
        App.get_running_app().review=""
        try:
            Student_Selection.getselfTL.clear_widgets()
        except:
            pass
        files=self.files
        Student_Selection.clear_widgets(self.val,children=None)
        try:
            if Student_Selection.student==[]:
                if files==[]:
                       App.get_running_app().s_0 ='invalid input'
                for file in files:
                    with open(file, "r") as opfile:
                        rows = csv.reader(opfile)
                        header = next(rows)
                        cnn = sqlite3.connect("KivyAppData.db")
                        cr = cnn.cursor() 
                        for data in rows:
                            Marks = file[:-4][-3:]
                            Name=""
                            splited_name=data[0].split()
                            for name in splited_name:
                                if name==splited_name[len(splited_name)-1]:
                                    Name+=""+name
                                else:
                                    Name+=name[0].upper()
                            if file == files[0]:
                                Student_Selection.student.append(Name)
                                cr.execute(f"drop table if exists {data[0]}")
                                cr.execute(f"create table {data[0]}{('Subjects', Marks)}")
                                column = [(header[number], data[number]) for number in range(1, len(data))]
                                cr.executemany(f'insert into {data[0]}("Subjects","{Marks}") values(?,?)',
column)
                            else:
                                cr.execute(f"alter table {data[0]} add {Marks}")
                                for number in range(1, len(data)):
                                    cr.execute(
                                        f"update {data[0]} set {Marks}=\'{data[number]}\' where Subjects=\'{header[number]}\'")
                        cnn.commit()
                        cnn.close()                     
            Student_Selection.studentfunc(self.val)
            if App.get_running_app().s_0 !='invalid input':
                App.get_running_app().sm.transition.direction='left'
                App.get_running_app().sm.current='tablescreen'
        except:
            App.get_running_app().s_0 ='invalid input'
        
class TableLabel(Label):
    pass

class TableScreen(Screen):
    def backfunc(self):
        App.get_running_app().s_0 = ''


class Student_Selection(GridLayout):
    student =  []
    getselfTL=0
    parent = None
    def __init__(self, **kwargs):
        super(Student_Selection, self).__init__(**kwargs)
        MainScreen.val = self
        self.cols = len(self.student)
        self.bind(minimum_height=self.setter('height'))

    def studentfunc(self):
        for i in self.student:
            self.add_widget(StudentButton(text=i, size_hint_y=None, height=35,on_release=self.Go_to_table))
    
    def Go_to_table(self,instance):
        Tablelayout.table(self.getselfTL, txt=instance.text)

class Tablelayout(GridLayout):
    def __init__(self, **kwargs,):
        super(Tablelayout, self).__init__(**kwargs)
        Student_Selection.parent = self
        Student_Selection.getselfTL=self
        self.bind(minimum_height=self.setter('height'))
    def table(self,txt):
        cnn = sqlite3.connect("KivyAppData.db")
        cr = cnn.cursor() 
        cr.execute(f"select * from {txt}")
        names=[d[0] for d in cr.description]
        self.cols=len(names) #2
        rows=list(cr.fetchall())
        self.rows=len(rows)+1 #6
        review_1=""
        subject=""
        try:
            self.clear_widgets()
        except:
            pass
        for header in names:
            self.add_widget(TableLabel(text=header))
        self.max_subject=""
        self.max_mark="0/1"
        self.min_subject=""
        self.min_mark="1000000/1"
        for row in rows:
            increase=0
            decrease=0
            constant=0
            subject=row[0]
            review_increase=[
            f"The student's performance in {subject} has improved.",
            f"{subject} performance is showing a positive trend.",
            f"In the subject of {subject}, the student's performance has risen.",
            f"{subject} performance is on the rise, exhibiting improvement.",
            f"The student has demonstrated improvement in {subject} performance.",
            f"{subject} proficiency has grown, showcasing enhancement.",
            f"A positive trend is evident in {subject} performance.",
            f"The student's mastery of {subject} has advanced.",
            f"{subject} scores have elevated, indicating improvement.",
            f"With a surge, the student has excelled in {subject} performance."
            ]
            review_decrease=[
            f"The student's performance in {subject} has declined.",
            f"{subject} performance is exhibiting a negative trend.",
            f"In the subject of {subject}, the student's performance has decreased.",
            f"{subject} performance is on the decline, showing a decrease.",
            f"The student's performance in {subject} has taken a downturn.",
            f"{subject} proficiency has decreased, indicating a decline.",
            f"A negative trend is evident in {subject} performance.",
            f"The student's mastery of {subject} has regressed.",
            f"{subject} scores have dropped, signaling a decrease.",
            f"With a decline, the student's performance in {subject} has weakened."
            ]
            review_constant=[
            f"The student's performance in {subject} remains consistent.",
            f"{subject} performance is stable, showing a consistent level of achievement.",
            f"In the subject of {subject}, the student's performance is steady.",
            f"{subject} performance has demonstrated a consistent level of proficiency.",
            f"The student has maintained a stable performance in {subject}.",
            f"{subject} proficiency is consistent, indicating a sustained level of achievement.",
            f"The student's performance in {subject} shows reliability and consistency.",
            f"{subject} scores have remained constant, reflecting a consistent performance.",
            f"With a consistent effort, the student excels in {subject} performance.",
            f"The subject of {subject} exhibits a consistently high level of performance."
            ]
            for index in range(len(row)):
                content=row[index]
                self.add_widget(TableLabel(text=content))
                if content!=subject:
                    object_1=int(content.split("/")[0])
                    if object_1>int(self.max_mark.split("/")[0]):
                        self.max_mark=content
                        self.max_subject=subject
                    if object_1<int(self.min_mark.split("/")[0]):
                        self.min_mark=content
                        self.min_subject=subject
                    if content!=row[len(row)-1]:
                        object_2=int(row[index+1].split("/")[0])
                        if object_2>object_1:
                            increase+=1
                        elif object_2<object_1:
                            decrease+=1
                        else:
                            constant+=1
            review_max= [ 
            f"The student has excelled to the maximum in {self.max_subject}.",
            f"In {self.max_subject}, the student has achieved the highest possible level of proficiency.",
            f"{self.max_subject} performance has reached the pinnacle with the student achieving the maximum.",
            f"The student has attained the maximum score in {self.max_subject}.",
            f"{self.max_subject} mastery is showcased as the student attains the maximum level of achievement.",
            f"In {self.max_subject}, the student's achievement has soared to the maximum.",
            f"The maximum level of proficiency in {self.max_subject} has been reached by the student.",
            f"{self.max_subject} scores reflect the student's attainment of the highest possible level.",
            f"The student has achieved the maximum in the subject of {self.max_subject}.",
            f"With outstanding performance, the student has reached the maximum in {self.max_subject}."
            ]
            review_min=[
            f"The student has scored the lowest in {self.min_subject}.",
            f"In {self.min_subject}, the student has attained the minimum level of proficiency.",
            f"{self.min_subject} performance has reached the lowest point with the student achieving the minimum.",
            f"The student has received the minimum score in {self.min_subject}.",
            f"{self.min_subject} mastery is at the lowest as the student attains the minimum level of achievement.",
            f"In {subject}, the student's achievement has fallen to the lowest.",
            f"The minimum level of proficiency in {self.min_subject} has been reached by the student.",
            f"{self.min_subject} scores reflect the student's attainment of the lowest possible level.",
            f"The student has achieved the lowest marks in the subject of {self.min_subject}.",
            f"With minimal performance, the student has reached the lowest in {self.min_subject}."
            ]
            if increase>decrease and increase>constant:
                review_1+=random.choice(review_increase)+" "
            elif decrease>increase and decrease>constant:
                review_1+=random.choice(review_decrease)+" "
            else:
                review_1+=random.choice(review_constant)+" " 
        review_1+=random.choice(review_max)+" "+random.choice(review_min) 
        App.get_running_app().review=review_1
        cnn.commit()
        cnn.close() 

class TestAnalysis(App):
    review=StringProperty("")
    s_0=StringProperty("")
    sm = ScreenManager()
    def build(self):
        self.icon="AppIcon.Ico"
        if getattr(sys, 'frozen', False):
            resource_add_path(sys._MEIPASS)
        Builder.load_file("thelab.kv")
        self.sm.add_widget(MainScreen(name="mainscreen"))
        self.sm.add_widget(TableScreen(name="tablescreen"))
        return self.sm

if __name__=="__main__":
    TestAnalysis().run()
#:import rgba kivy.utils.get_color_from_hex
<RoundedButton@Button>:
    background_color:(0,0,0,0)
    background_normal:''
    color:rgba('#fd6a02') if self.state =='normal' else rgba('ffffff')
    canvas.before:
        Color:  
            rgba:rgba('#fd6a02') 
        Line:
            rounded_rectangle:(self.pos[0],self.pos[1],self.size[0],self.size[1],15)
            width:1.2 
<StudentButton>:
    background_color:(0,0,0,0) if self.state=='normal' else (0,0,0,.3)
    background_normal:''

<RoundedButton1@Button>:
    background_color:(0,0,0,0)
    background_normal:''
    color:rgba('#ffffff')
    canvas.before:
        Color:  
            rgba:rgba('#fd6a02') if self.state =='normal' else rgba('0000ff')
        RoundedRectangle:
            size:self.size
            pos:self.pos
            radius:[15]

<TableLabel>:   
    size_hint:None,None
    width:140
    height:40

<MainScreen>:
    GridLayout:
        cols:2
        rows:1
        canvas.before:
            Rectangle:
                pos: self.pos
                size:self.size
                source: 'images (1).jpg'
        GridLayout:
            cols:2
            rows:1
            spacing:"5dp"
            size_hint:.5,1
            GridLayout:
                cols:1
                rows:3
                size_hint:None,1
                width:"400dp"
                spacing:10
                Label:
                    text:"Test\nAnalysis"
                    font_name:"Impact"
                    font_size:"100dp"
                    size_hint:1,.5
                GridLayout:
                    cols:2
                    rows:1
                    size_hint:1,.05
                    RoundedButton:
                        text:"Submit File"
                        size_hint:None,1
                        width:"100dp"
                        on_release:root.file_chooser1()
                    ScrollView:
                        size_hint:.7,1
                        canvas.before:
                            Color:
                                rgba:rgba('#80808080')
                            Rectangle:
                                size:self.size
                                pos:self.pos
                        Label:
                            text:app.s_0
                            font_name:"Georgia"
                            size_hint_y:None
                            height:self.texture_size[1]
                            text_size:self.width,None
                            color:rgba('#ffffff')
                            padding:[0,0,dp(100),0]
                AnchorLayout:
                    anchor_x:"center"
                    anchor_y:"top"
                    size_hint:1,.4
                    RoundedButton1:
                        text:"Enter"
                        size_hint_y:None
                        height:40
                        size_hint_x:None
                        width:150
                        on_release:root.Enter()
            ScrollView:
                size_hint:.5,1
                canvas.before:
                    Color:
                        rgba:(0,0,0,.7)
                    Rectangle:
                        size: self.size
                        pos: self.pos
                GridLayout:
                    cols:1
                    rows:7
                    do_scroll:True
                    size_hint:None,None
                    height:self.minimum_height
                    width:self.minimum_width
                    Label:
                        text:"The format of csv file must be like this:"
                        font_size:20
                        size_hint:None,None
                        size:self.texture_size
                    Image:
                        source:"Screenshot (23).png"
                        size_hint:None,None
                        size:400,400
                        allow_stretch:True
                    Label:
                        text:"Here s1,s2... are subjects and\nstudent0,student1... are name of student and\nmarks must be given in this format given marks/full marks"
                        font_size:20
                        size_hint:None,None
                        size:self.texture_size
                    Label:
                        text:"\nHere is sample input where two csv files are given\nuser is free to give any no. of files just press sumbit button that many times\nremember the last 3 letters of file is the name of examination"
                        font_size:20
                        size_hint:None,None
                        size:self.texture_size
                    Image:
                        source:"Screenshot (24).png"
                        size_hint:None,None
                        size:300,300
                        allow_stretch:True
                    Label:
                        text:"This is the ouput:"
                        font_size:20
                        size_hint:None,None
                        size:self.texture_size
                    Image:
                        source:"Screenshot (25).png"
                        size_hint:None,None
                        size:600,600
                        allow_stretch:True             
<TableScreen>:
    GridLayout:
        cols:1
        rows:2
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'images (1).jpg'
        AnchorLayout:
            size_hint:1,.1
            anchor_x:"left"
            anchor_y:"top"
            RoundedButton:
                text:"Back"
                size_hint_y:None
                height:"40dp"
                size_hint_x:None
                width:"100dp"
                on_release:
                    root.backfunc()
                    root.manager.transition.direction='right'
                    root.manager.current='mainscreen'
        GridLayout:
            size_hint:1,.9
            cols:2
            rows:1
            spacing:3
            GridLayout:
                rows:2
                size_hint:.4,1
                Label:
                    text:"STUDENTS"
                    size_hint_y:.05
                    font_name:"Georgia"
                    color:rgba('#ffffff')
                    canvas.before:
                        Color:
                            rgba:(1,1,1,.1)
                        Rectangle:
                            size: self.size
                            pos: self.pos
                ScrollView:
                    size_hint:1,.7
                    canvas.before:
                        Color:
                            rgba:(1,1,1,.1)
                        Rectangle:
                            size:self.size
                            pos:self.pos
                    Student_Selection:
                        cols:1
                        size_hint_y:None
                        spacing:3
            GridLayout:
                cols:1
                rows:2
                ScrollView:
                    size_hint:1,.5
                    canvas.before:
                        Color:
                            rgba:(1,1,1,.1)
                        Rectangle:
                            size:self.size
                            pos:self.pos
                    Tablelayout:
                        size_hint:None,None
                        height:self.minimum_height
                        width:self.minimum_width
                ScrollView:
                    size_hint:1,.5
                    canvas.before:
                        Color:
                            rgba:(1,1,1,.1)
                        Rectangle:
                            size:self.size
                            pos:self.pos
                    Label:
                        text:app.review
                        font_name:"Georgia"
                        size_hint_y:None
                        height:self.texture_size[1]
                        text_size:self.width,None
                        color:rgba('#ffffff')
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['TestAnalysis.py'],
    pathex=[],
    binaries=[],
    datas=[('thelab.kv', '.'), ('images (1).jpg', '.'), ('Screenshot (23).png', '.'), ('Screenshot (24).png', '.'), ('Screenshot (25).png', '.'), ('KivyAppData.db', '.'), ('AppIcon.ico', '.')],
    hiddenimports=['plyer.platforms.win.filechooser', 'kivy_deps.gstreamer', 'kivy_deps.angle', 'kivy.core.image.img_ffpyplayer', 'kivy.core.text.text_pil'],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='TestAnalysis',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['AppIcon.ico'],
)

python kivy pyinstaller exe
2个回答
0
投票

不确定这是否是问题所在,但查看我的一个项目中的工作规范文件,我发现我必须在规范文件的顶部包含

from kivy_deps import sdl2, glew 
。然后在
exe
部分使用它:

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
          .
          .
          .

我也需要:

         hiddenimports=['win32timezone'],

Analysis
部分。

另请注意,一旦有了

spec
文件,通常应该只运行
pyinstaller <name of spec file>
。您的所有
add-data
hidden-import
信息应该已经在您的
spec
文件中。


0
投票

刚刚添加了这段代码 '如果name==“main”: #从这一行开始 如果 hasattr(sys, '_MEIPASS'): resource_add_path(os.path.join(sys._MEIPASS)) #对此 测试分析().run()`

并修改了pyinstaller代码(只是删除了所有kivy相关代码)

pyinstaller --onefile -w --add-data="thelab.kv:." --add-data="图像 (1).jpg:." --add-data="屏幕截图 (23).png:." --add-data="屏幕截图 (24).png:." --add-data="屏幕截图 (25).png:." --add-data="KivyAppData.db:." --add-data="AppIcon.ico:" --icon=AppIcon.ico --hidden-import plyer.platforms.win.filechooser TestAnalysis.py

然后我就能够成功地将文件转换为一个 exe 文件,我没有修改规范文件中的任何内容

© www.soinside.com 2019 - 2024. All rights reserved.