简体   繁体   中英

Problem while converting Python code to exe via cx_freeze

I'm trying to convert a very simple code to exe. Code utilizes Kivy as follows;

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder

#from kivy import Config
#Config.set('graphics', 'multisamples', '0')

class MyLayout(Widget):
    
    def press(self, var_ex):

        name = self.ids.name_input.text
        self.ids.name_label.text = f"Hello {name} !" * var_ex


class MyApp(App):
    def build(self):

        return MyLayout()


if __name__.endswith('__main__'):from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder


Builder.load_string("""

<MyLayout>

    BoxLayout:
        orientation: "vertical"
        size: root.width, root.height
        spacing: 20
        padding: 50

        Button:
            text: "English"

        Button:
            text: "Italian"
            size_hint: ( None, None)
            width: 100
            height: 50
            pos_hint: { "center_x": 0.5}

        Button:
            text: "German"
            size_hint: ( 0.5, 0.5)

""")


class MyLayout(Widget):
    pass

class MyApp(App):
    def build(self):
        return MyLayout()


if __name__ == '__main__':
    MyApp().run()

This code works very well in python, with no errors. But when I try to convert it to exe via this setup.py file and cx_freeze;

import sys
from cx_Freeze import setup, Executable

build_exe_options = {"packages": ["kivy","pygame","kivy_deps.gstreamer"], "includes": ["kivy_deps.glew","kivy_deps.sdl2","wheel","setuptools","pygments","docutils","win32api","PIL"], "excludes": []}

#base = ""
base = "Win32GUI"

setup(
    name="guifoo",
    version="0.1",
    description="My GUI application!",
    options={"build_exe": build_exe_options},
    executables=[Executable("test.py", base=base)],
)

I get following error when running the created exe file (exe file is created without error);

Traceback (most recent call last):
   File "D:\Python310\kivy_venv\Lib\site-packages\cx_Freeze\initscripts\__startup__.py", line 113, in run
     module_init.run(name + "__main__")
   File "D:\Python310\kivy_venv\Lib\site-packages\cx_Freeze\initscripts\Console.py", line 15, in run
     exec(code, module_main.__dict__)
   File "test.py", line 1, in <module>
   File "D:\Python310\kivy_venv\lib\site-packages\kivy\__init__.py", line 317, in <module>
     mod = importer.find_module(modname).load_module(modname)
   File "D:\Python310\kivy_venv\lib\site-packages\kivy_deps\glew\__init__.py", line 23, in <module>
     p = join(d, 'share', 'glew', 'bin')
   File "D:\Python310\lib\ntpath.py", line 78, in join
     path = os.fspath(path)
 TypeError: expected str, bytes or os.PathLike object, not NoneType

Can somebody help me on this ? Thanks in advance...

PS I can give more information if requested.

So I still cannot figure out what the problem is with cx_freeze but, I was able to get it to work with PyInstaller. These are the steps I took.

pip install pyinstaller
cp test.py test

Inside the test file I had to remove both if __name__ == lines like below.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder

#from kivy import Config
#Config.set('graphics', 'multisamples', '0')

class MyLayout(Widget):
    
    def press(self, var_ex):

        name = self.ids.name_input.text
        self.ids.name_label.text = f"Hello {name} !" * var_ex


class MyApp(App):
    def build(self):

        return MyLayout()


from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder


Builder.load_string("""

<MyLayout>

    BoxLayout:
        orientation: "vertical"
        size: root.width, root.height
        spacing: 20
        padding: 50

        Button:
            text: "English"

        Button:
            text: "Italian"
            size_hint: ( None, None)
            width: 100
            height: 50
            pos_hint: { "center_x": 0.5}

        Button:
            text: "German"
            size_hint: ( 0.5, 0.5)

""")


class MyLayout(Widget):
    pass

class MyApp(App):
    def build(self):
        return MyLayout()


MyApp().run()

Then

pyinstaller -F --noconsole test

which will create the executable in the dist directory. I tested and this works. I still don't know why cx_freeze won't work though.

If your goal is to convert your program into a .exe, I would suggest using PyInstaller . You can easily install it using the command pip install pyinstaller in the command line. And there is no need for any setup.py file as well.

After installing it, simply navigate to the directory of the file you want to convert to an .exe (lets call this myFile.py ) and type the following in the command line:

pyinstaller myFile.py

This will create a few things in that directory:

  1. a file called myFile.spec
  2. a folder called build
  3. a folder called dist

The only important thing out of these is the dist folder. Inside it, you will find an .exe of your python script that you can run as an .exe. However, if you are importing files from directories that are relative to your myFile.py that are needed to run the .py script, simply move the myFile.exe to the same directory as myFile.py and it will work.

There are also additional arguments that you can add when converting to .exe that you can see on the pyinstaller website (ie, you can remove the console from appearing when running the .exe by adding --noconsole to the end of the command).

Hope that answers your question.

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