TypeError: no default __reduce__ due to non-trivial __cinit__

1,590 views
Skip to first unread message

Ben Shaw

unread,
Oct 28, 2022, 11:15:12 AM10/28/22
to Kivy users support
Hello , everyone!

       I am a beginner of python+kivy. I am working on an App. My App takes more than 12 seconds to startup. I don’t know why it needs such a long time . There are nearly 40 pages in my App, so I guess too many pages are the reason. In order to reduce the launch time, I try to use multiprocessing to load these pages, use 6 processes to load subfunctions(part 1~part6). But I failed with the log :“TypeError: no default __reduce__ due to non-trivial __cinit__”.  

Please find attached my main.py code and the running logs. I need help to solve the problem, or find other ways to speedup the App launch. I would be very appriciated if you can help to correct my code and make it runnable.

Thank you very much!

my main.py
#___________________________________________
#主程序入口
from kivy.app import App                                        
from kivy.uix.screenmanager import Screen,ScreenManager        
from kivy.core.window import Window

from kivy.resources import resource_add_path
from kivy.core.text import LabelBase,DEFAULT_FONT
resource_add_path('./site_packages')  # 全局申明载入字体
LabelBase.register(DEFAULT_FONT, 'simsun.ttf')
from multiprocessing import Process
import threading

#欢迎页面和主菜单

from pages.welcomepage.start1 import Start1Page
from pages.welcomepage.agreement import AgreementPage
from pages.welcomepage.help1 import Help1Page
from pages.welcomepage.help2 import Help2Page
from pages.welcomepage.help3 import Help3Page
from pages.welcomepage.welcome import WelcomePage
from pages.welcomepage.buykey import BuykeyPage
from pages.welcomepage.paybill import PaybillPage

from pages.mainmenupage.mainmenu import MainmenuPage
from pages.mainmenupage.agreement1 import Agreement1Page
from utils.outputrecycleview import OutputrecycleviewPage
from utils.jobimage import JobimagePage

#地基基础
from pages.categorypage.category1 import Category1Page          

from pages.jobpage.Base.job1a1 import Job1a1Page
from pages.jobpage.Base.job1a2 import Job1a2Page
from pages.jobpage.Base.job1a3 import Job1a3Page
from pages.jobpage.Base.job1a4 import Job1a4Page
from pages.jobpage.Base.job1a4image import Job1a4imagePage

#钢筋混凝土构件
from pages.categorypage.category2 import Category2Page          

from pages.jobpage.RC.job2a1 import Job2a1Page                      
from pages.jobpage.RC.job2a2 import Job2a2Page                      
from pages.jobpage.RC.job2a3 import Job2a3Page                      
from pages.jobpage.RC.job2a4 import Job2a4Page                      


from pages.jobpage.RC.job2b1 import Job2b1Page                      
from pages.jobpage.RC.job2b2 import Job2b2Page                      
from pages.jobpage.RC.job2b3 import Job2b3Page                      
from pages.jobpage.RC.job2b4 import Job2b4Page                      


from pages.jobpage.RC.job2c1 import Job2c1Page                      
from pages.jobpage.RC.job2c2 import Job2c2Page                      
from pages.jobpage.RC.job2c3 import Job2c3Page                      
from pages.jobpage.RC.job2c4 import Job2c4Page                      


from pages.jobpage.RC.job2d1 import Job2d1Page                      
from pages.jobpage.RC.job2d2 import Job2d2Page                      
from pages.jobpage.RC.job2d3 import Job2d3Page                      
from pages.jobpage.RC.job2d4 import Job2d4Page                      
from pages.jobpage.RC.job2d5 import Job2d5Page                      


from pages.jobpage.RC.job2e1 import Job2e1Page                      
from pages.jobpage.RC.job2e2 import Job2e2Page                      
from pages.jobpage.RC.job2e3 import Job2e3Page                      
from pages.jobpage.RC.job2e4 import Job2e4Page


from pages.jobpage.RC.job2f1 import Job2f1Page                      
from pages.jobpage.RC.job2f2 import Job2f2Page                      
from pages.jobpage.RC.job2f3 import Job2f3Page                      
from pages.jobpage.RC.job2f4 import Job2f4Page


def part1(self):
    print("part1")
    pages1={'Start1':Start1Page(),'Agreement':AgreementPage(),'Help1':Help1Page(),'Help2':Help2Page(),
           'Help3':Help3Page(),'Welcome':WelcomePage(),'Buykey':BuykeyPage(),'Paybill':PaybillPage()
           }
    for item,page in pages1.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return
       
def part2(self):
    print("part2")
    pages2={'Mainmenu':MainmenuPage(),'Agreement1':Agreement1Page(),'Category1':Category1Page(),
           'Category2':Category2Page(),'Outputrecycleview':OutputrecycleviewPage(),'Jobimage':JobimagePage()
           }
    for item,page in pages2.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return
       
def part3(self):
    print("part3")
    pages3={'Job1a1':Job1a1Page(),'Job1a2':Job1a2Page(),'Job1a3':Job1a3Page(),'Job1a4':Job1a4Page(),'Job1a4image':Job1a4imagePage(),
           'Job2a1':Job2a1Page(),'Job2a2':Job2a2Page(),'Job2a3':Job2a3Page(),'Job2a4':Job2a4Page()
           }
    for item,page in pages3.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return

def part4(self):
    print("part4")
    pages4={'Job2b1':Job2b1Page(),'Job2b2':Job2b2Page(),'Job2b3':Job2b3Page(),'Job2b4':Job2b4Page(),
           'Job2c1':Job2c1Page(),'Job2c2':Job2c2Page(),'Job2c3':Job2c3Page(),'Job2c4':Job2c4Page()
           }
    for item,page in pages4.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return

def part5(self):
    print("part5")
    pages5={'Job2d1':Job2d1Page(),'Job2d2':Job2d2Page(),'Job2d3':Job2d3Page(),'Job2d4':Job2d4Page(),'Job2d5':Job2d5Page(),
           'Job2e1':Job2e1Page(),'Job2e2':Job2e2Page(),'Job2e3':Job2e3Page(),'Job2e4':Job2e4Page()
           }
    for item,page in pages5.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return

def part6(self):
    print("part6")
    pages6={'Job2f1':Job2f1Page(),'Job2f2':Job2f2Page(),'Job2f3':Job2f3Page(),'Job2f4':Job2f4Page()
           }
    for item,page in pages6.items():
        self.default_page=page
        screen=Screen(name=item)
        screen.add_widget(self.default_page)
        self.screen_manager.add_widget(screen)
    return

class MyApp(App):
    def build(self):
         
        #Window.fullscreen=False
        #Window.size=(400,720)
        Window.size=(342,719)    #develop value
        Window.clearcolor=(1,1,1,1)


        self.load_kv("pages/welcomepage/start1.kv")
        self.load_kv("pages/welcomepage/agreement.kv")
        self.load_kv("pages/welcomepage/help1.kv")
        self.load_kv("pages/welcomepage/help2.kv")
        self.load_kv("pages/welcomepage/help3.kv")
        self.load_kv("pages/welcomepage/welcome.kv")
        self.load_kv("pages/welcomepage/buykey.kv")
        self.load_kv("pages/welcomepage/paybill.kv")
       

        self.load_kv("pages/mainmenupage/mainmenu.kv")
        self.load_kv("pages/mainmenupage/agreement1.kv")
        self.load_kv("utils/outputrecycleview.kv")
        self.load_kv("utils/jobimage.kv")

 
        self.load_kv("pages/categorypage/category1.kv")
     
        self.load_kv("pages/jobpage/Base/job1a1.kv")          
        self.load_kv("pages/jobpage/Base/job1a2.kv")          
        self.load_kv("pages/jobpage/Base/job1a3.kv")          
        self.load_kv("pages/jobpage/Base/job1a4.kv")
        self.load_kv("pages/jobpage/Base/job1a4image.kv")
       

  
        self.load_kv("pages/categorypage/category2.kv")
     
        self.load_kv("pages/jobpage/RC/job2a1.kv")          
        self.load_kv("pages/jobpage/RC/job2a2.kv")          
        self.load_kv("pages/jobpage/RC/job2a3.kv")          
        self.load_kv("pages/jobpage/RC/job2a4.kv")          
       

        self.load_kv("pages/jobpage/RC/job2b1.kv")          
        self.load_kv("pages/jobpage/RC/job2b2.kv")          
        self.load_kv("pages/jobpage/RC/job2b3.kv")          
        self.load_kv("pages/jobpage/RC/job2b4.kv")          


        self.load_kv("pages/jobpage/RC/job2c1.kv")          
        self.load_kv("pages/jobpage/RC/job2c2.kv")          
        self.load_kv("pages/jobpage/RC/job2c3.kv")          
        self.load_kv("pages/jobpage/RC/job2c4.kv")          


        self.load_kv("pages/jobpage/RC/job2d1.kv")          
        self.load_kv("pages/jobpage/RC/job2d2.kv")          
        self.load_kv("pages/jobpage/RC/job2d3.kv")          
        self.load_kv("pages/jobpage/RC/job2d4.kv")          
        self.load_kv("pages/jobpage/RC/job2d5.kv")          


        self.load_kv("pages/jobpage/RC/job2e1.kv")          
        self.load_kv("pages/jobpage/RC/job2e2.kv")          
        self.load_kv("pages/jobpage/RC/job2e3.kv")          
        self.load_kv("pages/jobpage/RC/job2e4.kv")
       

        self.load_kv("pages/jobpage/RC/job2f1.kv")          
        self.load_kv("pages/jobpage/RC/job2f2.kv")          
        self.load_kv("pages/jobpage/RC/job2f3.kv")          
        self.load_kv("pages/jobpage/RC/job2f4.kv")
   
        self.screen_manager=ScreenManager()
       
        #将各页面加入列表
        '''
        part1_process=Process(target=part1,args=(self,))
        part2_process=Process(target=part2,args=(self,))
        part3_process=Process(target=part3,args=(self,))
        part4_process=Process(target=part4,args=(self,))
        part5_process=Process(target=part5,args=(self,))
        part6_process=Process(target=part6,args=(self,))

        part1_process.start()
        part2_process.start()        
        part3_process.start()        
        part4_process.start()        
        part5_process.start()        
        part6_process.start()

        part1_process.join()
        part2_process.join()        
        part3_process.join()        
        part4_process.join()        
        part5_process.join()        
        part6_process.join()
       

        '''
        process=[Process(target=part1,args=(self,)),Process(target=part2,args=(self,)),Process(target=part3,args=(self,)),
                 Process(target=part4,args=(self,)),Process(target=part5,args=(self,)),Process(target=part6,args=(self,)) ]
        [p.start() for p in process]  # 开启了两个进程
        [p.join() for p in process]   # 等待两个进程依次结束

        '''
        part1(self)
        part2(self)
        part3(self)
       
        part4(self)
        part5(self)
        part6(self)
        #'''      
               
        return self.screen_manager


if __name__=="__main__":
    SGenie_app=MyApp()
    SGenie_app.title='结构精灵'
    SGenie_app.run()


running log:
#____________________________________________________________________________
================ RESTART: D:\0Myapp\0MyApp\client\main.py ================
[INFO   ] [Logger      ] Record log in C:\Users\xiaod\.kivy\logs\kivy_22-10-28_27.txt
[INFO   ] [deps        ] Successfully imported "kivy_deps.gstreamer" 0.3.3
[INFO   ] [deps        ] Successfully imported "kivy_deps.angle" 0.3.2
[INFO   ] [deps        ] Successfully imported "kivy_deps.glew" 0.3.1
[INFO   ] [deps        ] Successfully imported "kivy_deps.sdl2" 0.4.5
[INFO   ] [Kivy        ] v2.1.0
[INFO   ] [Kivy        ] Installed at "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\__init__.py"
[INFO   ] [Python      ] v3.10.7 (tags/v3.10.7:6cc6b13, Sep  5 2022, 14:08:36) [MSC v.1933 64 bit (AMD64)]
[INFO   ] [Python      ] Interpreter at "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\pythonw.exe"
[INFO   ] [Logger      ] Purge log fired. Processing...
[INFO   ] [Logger      ] Purge finished!
[INFO   ] [Factory     ] 189 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.6.0 - Build 30.0.100.9864'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Intel(R) Iris(R) Xe Graphics'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60 - Build 30.0.100.9864'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Clipboard   ] Provider: winctypes
 Traceback (most recent call last):
   File "D:\0Myapp\0MyApp\client\main.py", line 272, in <module>
     SGenie_app.run()
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\app.py", line 954, in run
     self._run_prepare()
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\app.py", line 924, in _run_prepare
     root = self.build()
   File "D:\0Myapp\0MyApp\client\main.py", line 253, in build
     [p.start() for p in process]  # 开启了两个进程
   File "D:\0Myapp\0MyApp\client\main-多进程尝试.py", line 253, in <listcomp>
     [p.start() for p in process]  # 开启了两个进程
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 121, in start
     self._popen = self._Popen(self)
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 224, in _Popen
     return _default_context.get_context().Process._Popen(process_obj)
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 336, in _Popen
     return Popen(process_obj)
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
     reduction.dump(process_obj, to_child)
   File "C:\Users\xiaod\AppData\Local\Programs\Python\Python310\lib\multiprocessing\reduction.py", line 60, in dump
     ForkingPickler(file, protocol).dump(obj)
   File "stringsource", line 2, in kivy._event.EventDispatcher.__reduce_cython__
 TypeError: no default __reduce__ due to non-trivial __cinit__
            

Robert

unread,
Oct 28, 2022, 12:54:51 PM10/28/22
to Kivy users support
Each Process has a different memory space, you can't combine memory results.
This is a characteristic of an operating system process.

You could use threads, the the Python GIL and the characteristics of your CPU will determine if that helps enough.

This document was written for Kivy on Android, but applies here
https://github.com/Android-for-Python/Android-for-Python-Users#slow-app-start
Note paragraphs 2 and 3. This moves most of the loading till after the app has started.

Elliot Garbus

unread,
Oct 28, 2022, 1:14:06 PM10/28/22
to kivy-...@googlegroups.com

You can not use multiprocessing in this case.  In multiprocessing each process has a separate address space. 

 

When addressing performance issues it is always best to profile your code so you understand where the time is being spent.

Read:

https://kivy.org/doc/stable/api-kivy.app.html?highlight=profile#profiling-with-on-start-and-on-stop

https://docs.python.org/3/library/profile.html

 

I will make a few assumptions on the source of your problem, and make some suggestions.   Give you are creating 40 pages, and the each page will have multiple widgets, it is quite likely the startup time issue is caused by the time spent creating all of the widgets.  There are 2 alternatives:

  1. Create fewer Widgets
  2. Defer creating some of the widgets until after startup

 

Create Fewer Widgets

In your specific case, I would suggest creating fewer widgets.  You have 40 pages, I suspect that many of the pages have the same data layout (they look the same) but the display different data.  If this is correct you could significantly reduce the number of pages, and just change the data that is displayed to the user on a single page.

I had a similar issue where I had 16 pages each with the same rather complicated widgets. I had been using 16 buttons to select between the pages.  I modified the code so there were effectively no screens.  The buttons were used to select which data to display.  I provided the same user experience as the 16 pages, but with 1/16th the number of widgets.  This change dramatically reduced startup time.

 

Defer Creating some Widgets until after Startup:

An alternative if you feel you must have 40 separate pages of widgets would be to defer loading the pages.  You could for example load 1 screen, a welcome screen at startup, and include a progress bar on that screen.  The after the welcome screen is displayed, load the other screen to and use the progress bar to show the screens are loading.  Informing the user that the app is getting prepared to run.

 

Additionally, Looking at your code below I have a few suggestions:

Don’t repeat code:  The code for the methods part1 through part6 is almost identical.  You could create a single method where the number is passed in and reduce the amount of code.  When code is repeated like this it becomes error prone and difficult to maintain.  If you find an error it must be fixed 6 times.  A good friend of mine likes to say, “If you have written the same code 3 times, you done it wrong twice.”

 

You are loading a number of kv files.   Instead of writing them all out explicitly you could use glob to get a list of all the kv files in the directory, and load the files in a loop.  You can use the glob module or the more modern (but a little more complicated) pathlib.

 

See:

https://docs.python.org/3/library/glob.html

https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob

 

 

Good Luck!

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63b87024-1ac0-40e8-90c9-48cde6145050n%40googlegroups.com.

 

Ben Shaw

unread,
Oct 28, 2022, 9:59:00 PM10/28/22
to Kivy users support
Thanks for your reply!

Ben Shaw

unread,
Oct 28, 2022, 10:36:35 PM10/28/22
to Kivy users support
Thanks for your reply!
Reply all
Reply to author
Forward
0 new messages