简体   繁体   中英

Pyinstaller and pygubu's calendar frame cause a problem

I made a pygubu python application, and decided I wanted to freeze it, after troubleshooting some simple problems, I ran into something I couldn't fix:

Traceback (most recent call last):
  File "main.py", line 138, in <module>
  File "pygubu\__init__.py", line 30, in __init__
  File "main.py", line 38, in _create_ui
  File "pygubu\builder\__init__.py", line 166, in get_object
  File "pygubu\builder\__init__.py", line 215, in _realize
  File "pygubu\builder\__init__.py", line 215, in _realize
  File "pygubu\builder\__init__.py", line 225, in _realize
Exception: Class "pygubu.builder.widgets.calendarframe" not mapped
[13108] Failed to execute script 'main' due to unhandled exception!

I even imported a bunch of pyugubu modules to try to fix this, and it still didn't work:

from pygubu import builder
from pygubu.builder import ttkstdwidgets
from pygubu.builder import widgets
from pygubu.widgets import calendarframe
from pygubu import widgets

This probably doesn't matter, but I froze it with auto-py-to-exe. I've tried making it a console application, folder application, and both at the same time, but it still didn't work.

Thank you in advance.

1. Create test-project

Create test.py (adapted from here ) (i included all the dependencies you mentioned and listed their attributes and methods to make sure the module is included):

import tkinter as tk
import pygubu
from pygubu import builder
from pygubu.builder import ttkstdwidgets
from pygubu.builder import widgets
from pygubu.widgets import calendarframe
from pygubu import widgets

class HelloWorldApp:
    
    def __init__(self):

        #1: Create a builder
        self.builder = builder = pygubu.Builder()

        #2: Load an ui file
        builder.add_from_file('test.ui')

        #3: Create the mainwindow
        self.mainwindow = builder.get_object('mainwindow')
        
    def run(self):
        self.mainwindow.mainloop()


if __name__ == '__main__':
    # just some calls to make sure the imports are loaded
    print(dir(pygubu))
    print(dir(builder))
    print(dir(ttkstdwidgets))
    print(dir(widgets))
    print(dir(calendarframe))
    print(dir(widgets))
    
    app = HelloWorldApp()
    app.run()

Create test.ui :

<?xml version='1.0' encoding='utf-8'?>
<interface>
  <object class="tk.Toplevel" id="mainwindow">
    <property name="height">200</property>
    <property name="resizable">both</property>
    <property name="title" translatable="yes">Hello World App</property>
    <property name="width">200</property>
    <child>
      <object class="ttk.Frame" id="mainframe">
        <property name="height">200</property>
        <property name="padding">20</property>
        <property name="width">200</property>
        <layout>
          <property name="column">0</property>
          <property name="propagate">True</property>
          <property name="row">0</property>
          <property name="sticky">nsew</property>
          <rows>
            <row id="0">
              <property name="weight">1</property>
            </row>
          </rows>
          <columns>
            <column id="0">
              <property name="weight">1</property>
            </column>
          </columns>
        </layout>
        <child>
          <object class="ttk.Label" id="label1">
            <property name="anchor">center</property>
            <property name="font">Helvetica 26</property>
            <property name="foreground">#0000b8</property>
            <property name="text" translatable="yes">Hello World !</property>
            <layout>
              <property name="column">0</property>
              <property name="propagate">True</property>
              <property name="row">0</property>
            </layout>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

2. Install pyinstaller and pygubu

pip install pyinstaller pygubu

3. Copy pygubu module to local project

  1. Navigate to site-packages folder of current interpreter (execute in shell: python -c "import site; print(site.getsitepackages()[-1])" , navigate to returned path)
  2. Copy entire pygubu folder to location with test.py script

One-liner from within the folder containing test.py :

python -c "import shutil, site, os; shutil.copytree(site.getsitepackages()[-1]+os.sep+'pygubu', os.getcwd()+os.sep+'pygubu')"

4. Run pyinstaller, test package

The following statement adds the .ui file as well as the entire pygubu package directly. Afterwards, run the test.exe from within the dist/test folder.

pyinstaller --clean --add-data=test.ui;. --add-data pygubu;pygubu test.py

I tried running pyinstaller with --onefile which did not work, --hidden-import , --collect-data , --collect-submodules and --collect-all also failed. This is quite an ugly solution, however.


Edit

After discovering what an awesome module auto-py-to-exe is (thank you for mentioning it), i discovered that you can use --collect-all in combination with --onefile without the need of copying the pygubu library by hand. However, i could not manage to include the.ui file, so that i had to copy manually:

pyinstaller --noconfirm --onefile --windowed --collect-all "pygubu"  "test.py" && python -c "import shutil, os; shutil.copyfile('test.ui', 'dist'+os.sep+'test.ui')"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM