Eugene B
Eugene B

Reputation: 47

Nuitka and Kivy C extension module _event.so

I am attempting to use Nuitka to create a standalone executable from this basic Kivy example hello.py:

from kivy.app import App
from kivy.uix.button import Button

class TestApp(App):
    def build(self):
        return Button(text='Hello World')

TestApp().run()

When I do python -m nuitka --follow-imports hello.py, Nuitka creates the executable, but when I run this, it fails with

../dist-packages/kivy/event.py", line 8, in import kivy._event No module named _event

The module _event is in fact the c extension module _event.so which Python interpreter finds and loads OK.

My question is - what causes this error? Can I get around this?

It appears that Nuitka can deal with c extension modules generally, e.g. doing python -m nuitka --follow-imports on

from bluetooth import bluez as _btz
print _btz._bt
print "Hello World!"

results in a functioning executable even though module bluez has an import _bluetooth statement referring to a _bluetooth.so extension module:

./hello.bin

<module 'bluetooth._bluetooth' from '/usr/lib/python2.7/dist-packages/bluetooth/_bluetooth.so'>

Hello World!

In case it is relevant: system is MX Linux 18.3 (Debian Stretch based), Python 2.7.13, Kivy v1.10.1, Nuitka 0.6.8.4

My objective is to speed up Kivy application startup time, as opposed to packaging the application for distribution. For example, I have a RPI2B embedded system running a Kivy app on Buildroot generated Linux. This cold boots in 12 seconds, of which 6 seconds is Kivy app startup time. So for example PyInstaller does not help me here, whilst Nuitka potentially could.

UPDATE

I gave up trying to get this to work with Python 2.7 not sure what happened but I ran into some Nuitka infinite optimisation loop problem. Got a bit further with Python 3.5, these are my notes from when I did it:

sudo apt-get update
sudo apt-get install python3-pip
sudo apt-get install python3-setuptools
sudo apt-get install python3-dev
sudo apt-get install mesa-common-dev
sudo apt install libgl1-mesa-dev
sudo apt-get install chrpath
pip3 install wheel
pip3 install pygame
pip3 install kivy (ended up with 1.11.1)
pip3 install nuitka

followed clues from here https://github.com/kivy/kivy/wiki/Packaging-Kivy-apps-written-in-Python-3,-targeting-Windows-using-Nuitka

Create dependencies.py:

# external modules
import kivy.cache
import kivy.atlas
import kivy.network
import kivy.network.urlrequest
#import kivy.lib.osc
#import kivy.lib.osc.OSC
#import kivy.lib.osc.oscAPI
import kivy.lib.mtdev
#import kivy.lib.sdl2
import kivy.factory_registers
import kivy.input.recorder
import kivy.input.providers
import kivy.input.providers.tuio
import kivy.input.providers.mouse
#import kivy.input.providers.wm_common
#import kivy.input.providers.wm_touch
#import kivy.input.providers.wm_pen
import kivy.input.providers.hidinput
import kivy.input.providers.linuxwacom
#import kivy.input.providers.mactouch
import kivy.input.providers.mtdev

# compiled modules
import kivy.event
import kivy.graphics.buffer
#import kivy.graphics.c_opengl_debug
import kivy.graphics.compiler
import kivy.graphics.context_instructions
import kivy.graphics.fbo
import kivy.graphics.instructions
import kivy.graphics.opengl
import kivy.graphics.opengl_utils
import kivy.graphics.shader
#import kivy.graphics.stenctil_instructions
import kivy.graphics.texture
import kivy.graphics.transformation
import kivy.graphics.vbo
import kivy.graphics.vertex
import kivy.graphics.vertex_instructions
import kivy.graphics.tesselator
import kivy.graphics.svg
import kivy.properties
import kivy.graphics.cgl_backend

# core
# import kivy.core.audio.audio_gstplayer
# import kivy.core.audio.audio_pygst
import kivy.core.audio.audio_sdl2
# import kivy.core.audio.audio_pygame
# import kivy.core.camera.camera_avfoundation
# import kivy.core.camera.camera_pygst
# import kivy.core.camera.camera_opencv
# import kivy.core.camera.camera_videocapture
import kivy.core.clipboard.clipboard_sdl2
# import kivy.core.clipboard.clipboard_android
# import kivy.core.clipboard.clipboard_pygame
# import kivy.core.clipboard.clipboard_dummy
# import kivy.core.image.img_imageio
# import kivy.core.image.img_tex
# import kivy.core.image.img_dds
import kivy.core.image.img_sdl2
# import kivy.core.image.img_pygame
# import kivy.core.image.img_pil
# import kivy.core.image.img_gif
# import kivy.core.spelling.spelling_enchant
# import kivy.core.spelling.spelling_osxappkit
import kivy.core.text.text_sdl2
# import kivy.core.text.text_pygame
# import kivy.core.text.text_sdlttf
# import kivy.core.text.text_pil
# import kivy.core.video.video_gstplayer
# import kivy.core.video.video_pygst
# import kivy.core.video.video_ffmpeg
# import kivy.core.video.video_pyglet
# import kivy.core.video.video_null
import kivy.core.window.window_info
import kivy.graphics.cgl_backend.cgl_glew
import kivy.graphics.cgl_backend.cgl_gl
import kivy.graphics.cgl_backend.cgl_sdl2
import kivy.core.window.window_sdl2
#import kivy.core.window.window_egl_rpi
# import kivy.core.window.window_pygame
# import kivy.core.window.window_sdl
# import kivy.core.window.window_x11

Use it like this:

python3 -m nuitka --include-plugin-files=dependencies.py --standalone hello.py
cp -r <path/to>/lib/python3.5/site-packages/kivy/data <path/to>/hello.dist/kivy/
./hello.dist/hello

Any "ImportError: No module named <...>" is remedied by adding a corresponding import statement in dependencies.py

However resulting executable appears to be no faster than original python script. And it wouldn't run under a separate MX Linux instance on the same machine, I got this:

X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  155 (GLX)
  Minor opcode of failed request:  3 (X_GLXCreateContext)
  Value in failed request:  0x0
  Serial number of failed request:  72
  Current serial number in output stream:  73

Upvotes: 2

Views: 942

Answers (1)

Caleb Sword
Caleb Sword

Reputation: 31

In January 2022, an official Kivy plugin for Nuitka was introduced and it is automatically used if Nuitka detects that your project uses Kivy. For me, writing the example "hello world" app in a file called main.py and then running python -m nuitka --standalone main.py in main.py's directory produces a functional executable.

I am using Python 3.11.4, Kivy 2.2.1, and Nuitka 1.7.10.

Upvotes: 1

Related Questions