Skip to main content

Kivy vs Enaml native - A comparision

Since it was asked on HackerNews I thought I'd do a post that compares Kivy and enaml-native.  This should help you to decide which framework to choose to use when and why as they both have pros and cons.

Let me also state that I'm the author of enaml-native and thus I cannot give a truly unbiased comparison. With that aside. Let's begin.


Kivy and enaml-native have similar but slightly different goals. Kivy's tagline is "Open source UI framework written in Python" while enaml-native's is "Build native mobile apps in python with enaml".  Kivy aims to support desktop (windows, mac, linux), mobile (android, ios), and the raspberry pi. enaml-native targets only iOS and android (as enaml already does windows, mac, and linux).

The huge difference between the two here is that Kivy has it's own widget framework, while enaml and enaml-native use native widgets.  The rest is about the same. They're both made for building apps/programs in python.




I spent several weeks contributing to the KivyMD project attempting to recreate the material design look for Kivy that you get out of the box when using enaml-native. It was so much work, I'm still the #4 contributor of the project!


I tried to compare the two on a bunch of different levels (sorry for the terrible formatting).

LanguageCython / PythonPython / C++
Object frameworkKivy propertiesAtom framwork
Event loopKivy clocktornado / twisted

User Interface

UI languageKV langEnaml
Widget frameworkKivy UXNative
Custom widgetsYesNo
Native widgetsNoYes
Looks nativeNoYes
Conditional renderingIn codeDeclaratively
Repeated renderingIn codeDeclaratively
Event handlersIn codeDeclaratively
Extend widgetsYesYes
Widgets Multiple inheritanceYesNo
Declarative data bindingOne wayTwo way
Python in separate thread from UINoYes
LayoutsKivy UXFlexbox / Native

Packaging and Building

Build systembuildozerenaml-native-cli
Config filebuildozer.specpackage.json
Pip installableYesYes
Pip installable recipesNoYes
Versioned recipesNoYes
Apps have own venvNoYes
Add on packagesKivy gardenenaml-native packages (pip)

OS integration

Android interfacepyjniusAsync bridge
iOS interfacepyobjcAsync bridge
PermissionsManifest onlyRuntime & Manifest
GPS integrationYesYes
Text integration PlierIntent
Phone integrationPlierIntent
Wifi apipyjnius / pobjusYes
Bluetooth apipyjnius / pyobjusSoon

Debugging features

Code reloadingNoYes
Remote debuggingDesktop onlyYes
Hot swappingNoPartial
Run in Android studio / xcodeNoYes
Runs locallyYesEmulator




Age~7 years~6 months

Feel free to correct something or suggest a new field be compared!

So, which to use, when?

Just different UI frameworks

Kivy is a true cross platform UI framework. It provides it's own widget toolkit using KV lang and it's own api to OpenGL ES 2. This is great for custom interfaces or where you need to create your own widgets, such as games or customized UI's and it works cross platform as it depends only on OpenGL ES2.

enaml-native (and enaml) the other hand, is a framework for declaring user interfaces with an abstraction from the toolkit that implements the widgets. enaml-native simply lets you declare a UI using native android widgets (or Qt for the desktop).

So if you want your apps to look native like other apps or programs on the system, then Kivy may not be the best fit, try enaml-native. If you need customized widgets then Kivy is an excellent choice.

Native integration

If you need to reuse existing native libraries, this is where enaml-native really starts to shine. Since it is simply wrapping a native widget, you can reuse widgets others already created instead of having to write them yourself. I created the enaml-native-barcode package and an app to demonstrate it in about 4 hours, without knowing a single thing about barcode scanning before starting.  It works fantastic, see


If you only need to use some native API's both Kivy and enaml-native have tools to do native integration, but pyjnius and pyobjc are easier to use (as they're not async) and use reflection to build the classes for interfacing.  If you like async programming or need to do a lot of native calls then enaml-native is your best bet, otherwise Kivy's tools work great.

Declarative code

KVlang works for "declaring" interfaces however is is much more limited than enaml.  They are both excellent for binding model properties to a view. KVlang is great for making custom widgets (see KivyMD ).

However, Kvlang does not support conditional or pattern (ex for loop) based generation like enaml, which means Kivy requires mixing UI and handling code for any kind of dynamic rendering (adding or removing nodes). Enaml is much cleaner in this regard.

With enaml, you can literally define entire apps declaratively using only models for handling state and any external API calls (such as a network resource).

So if you like declarative programming then enaml-native is awesome. If you're more of a functional or imperative programmer, then maybe kivy is a better choice for you.

Community and Docs

Kivy is without a doubt a winner here. Kivy has been around since 2011 and has accumulated ~7k stars on github. It has an active development team with about a dozen members.  It's documentation is excellent.

enaml-native has only been started a little over 6 months ago at as of this post has close ~30 stars (despite no promotion on my end whatsoever). It's probably too early for a valid comparison here.  The documentation for enaml-native needs a lot of work yet.


enaml-native has been slowly growing. Everyone is skeptical to try something with only a few stars but I think it will continue to grow. I used this framework to build multiple personal apps (my house is controlled by one) that I use nearly every day so I plan to continue developing enaml-native for a very long time.

It is also being used by a startup company and I've been told about plans a few others have for the framework so hopefully they can start sharing their unbiasd experiences with it!

Hopefully this helps give an idea about when to use which framework. I don't think Kivy and enaml-native are competing, more like complimenting each other.

Any questions? Please comment below.

Oh, and have a Merry Christmas!


  1. Thank you for your great work. It's far the best web framework based on Python.


Post a Comment

Popular posts from this blog

Kivy vs React-Native for building cross platform mobile apps

I've built three apps now using Kivy and one with React-Native, just wanted to share my thoughts on both.

Just a warning, I am strongly biased towards python and this is all based on opinion and experience and is thus worth what you pay for it. I don't claim to be an expert in either of these, just have worked with each for several months.  If something is incorrect I'd love to hear advice.

Demo of one of the apps

Nice to be able to run natively on the desktop WITHOUT a simulatorPython is easy to work withUse (almost) any python libraryVery easy to create custom widgetsKivy properties and data binding just work. Way nicer than React's "state" / flux / redux whatever you want to call it (stupid?). Native interfaces (pyjnius) and (pyobjc)Runs and feels pretty smooth Cons:Default widget toolkit looks like Android 4.4. Requiring you use your own widgets or a theming kit like KivyMD if styling bothers youCreating dynamic widgets declaratively is not yet s…

Control Systems in Python - Part 1 - Bode and Step Response

I hate matlab with passion, yet sadly, nearly everyone uses it.  I'm a fan of Python and open source stuff so here's a simple article on how to do some common control systems stuff in Python.

First we need to make sure the environment is setup.
Install IPython (or you can use any other python shell, but a unicode supported shell is preferred)Install python-control (numpy, scipy)Install sympy
These should do if your on Ubuntu/debian:

sudo apt-get install python-sympy python-numpy python-scipy python-matplotlib ipython
Then you need to install python control, see How to download and install python-control
Intro to using SympyOpen ipython and run the following:

import sympy from sympy import * sympy.init_printing() s = Symbol('s')

Now we can do things like define transfer functions using the symbolic variable s.

We can expand the bottom using the .simplify() method

and we can do something more complex like...
which is really nice because it does all the multiplication for us... and it’…