React Native and Python – run Python script on the frontend side

Introduction

This article serves as a quick summary / indication for anyone who wants to use Python on the frontend side. And this article only focuses on the Android part. 

Probably you will not find on the Internet any articles about how to use React Native and Python. Most of the articles will suggest you to use Python on the backend side. Actually, it is a good idea to use Python on the backend side. But in this case I am going to explain how to use Python on the front side. I called that method “ Inject ”, since we’re gonna try to inject a Python script and use a custom native module to communicate with Javascript. Let’s get started and grab your coffee then.

https://github.com/arwysyah/React_Native_Python_and_Research_Bridge

What you need to know: 

  • Javascript
  • Java
  • React Native
  • Native Module

Let’s go!

Question 

Can I use Python in the React Native project? The answer depends.

If you want to replace Javascript with Python, of course it’s not possible since React Native uses JSI to Communicate with JNI. Instead, you can compile the Python script using Chaquopy Since Chaquopy is possible to run on an Android platform, it means that React Native has the possibility to make the same thing too.

Thanks to the Chaquopy author: Malcolm Smith, aka mhsmith , and team for creating such an awesome project.
Thanks to our project Code All that inspired me to research the possibility of implementing this topic.
Thanks to my CEO for letting me write this project as an article.

Chaquopy

What is Chaquopy  ?

Chaquopy  is a Python SDK that lets you communicate with Java API.
Probably you know some Python frameworks that can build Android apps, such as Kivy which uses pyjnius to communicate with JNI to access Java Class, or RubyMotion which is a Ruby language to build Mobile Platform. Chaquopy provides everything you need to include Python components in an Android app, including:
1. Full integration with Android Studio’s standard Gradle Build System.
2. Simple APIs for calling Python Code from Java / Kotlin and vice versa.
3. A wide range of third-party Python libraries, including Scipy, OpenCV, TensorFlow and many more.
4. Chaquopy is thread-safe.However, because it’s based on CPython (the Python reference implementation), it is limited by

CPython’s global interpreter lock (GIL). This means that although Python code may be run on any number of threads, only one of those threads will be executing at any given moment.

How to Implement Chaquopy in React Native?
For Android or Java configuration you can take a look at the documentation here .
But in React Native it’s a bit different, since we only have one Activity.

Basic setup

Gradle plugin

In your project’s settings.gradle or build.gradle file, find the repositories list in pluginManagement buildscript, and make sure it includes mavenCentral (). If your project was generated by a recent version of Android Studio, this line should already be there.

In your top-level build.gradle file 

{your_project_name} /android/app/build.gradle

(eg: react-native-research-bridge / android / app / build.gradle)

set the Chaquopy version:
ABI Filter
The Python interpreter is a native component, so you must use the abiFilters setting to specify which ABIs you want the app to support. The currently available ABIs are:

  • armeabi-v7a, supported by virtually all Android devices.
  • arm64-v8a, supported by most recent Android devices.
  • x86, for the Android emulator.
  • x86_64, for the Android emulator.

During development you’ll probably want to enable them all, ie:

Development

Source Set

By default, Chaquopy will look for Python source code in the Python subdirectory of each source set . For example, the Python code for the main source set should go in src / main / python.

To include Python source code from other directories, use the android.sourceSets block. For example:

Requirements

This feature requires Python on the build machine, which can be configured with the buildPython setting.

External Python packages may be built into the app using the pip block in build.gradle inside the default config block. Within this block, add install lines, which can take any of the forms accepted by pip install . For example:

Since we are using React Native, we need to make this step a bit different from what is written in Chaquopy Documentation.

First, we need to import Android OS Bundle in our MainActivity file. The purpose of this step is to be able to invoke the OnCreate (Bundle) function inside this activity. OnCreate (Bundle) will be called when the application starts which is a good place to put Python checking and start the Python.

Here it would be look like this: MainActivity.java

Then you can put an “android log” inside of the condition to check if it’s working already or not. If it works, it means you can start working with your Python file… but with Native Modules.

Create Native Modules to Run Python File 

Okay… since our configuration was successfully created, we need to implement Native Modules in React Native, so we can access Python from Java and communicate with Javascript. You can read about native modules here .
You can follow my steps too.

  1. Since you are going to work with Java or Kotlin, I suggest you to open Android Studio but keep your VS Code or your Javascript IDE active. That’s gonna help us with our development, especially with the debugging process. 
  2. When you successfully open your project in Android Studio, it’s gonna take a while to build the gradle, doesn’t it? Lol,  I feel that.
  3. Ok, let’s assume you are able to take a look at your project directory structure. Then you can take a look at your folder that stores your MainActivity & MainApplication. It’s gonna be placed in android/app/src/main/java/com/{your-app-name}/ .
  4. Click the folder and create Java Class and your file name. Let’s name it “PythonModules”.
  5. And let’s edit our PythonModules to be like code below :

    Here is an explanation of ReactContextBaseJavaModule:

    ReactContextBaseJavaModule gives access to the ReactApplicationContext (RAC), which is useful for Native Modules that need to hook into activity lifecycle methods. Using ReactContextBaseJavaModule will also make it easier to make your native module type-safe in the future. For native module type-safety, which is coming in future releases, React Native looks at each native module’s JavaScript spec and generates an abstract base class that extends ReactContextBaseJavaModule.

     

  6. Let’s create a Java function (React method) inside this file, go modify this file then. We can call it later from the Javascript side. Let’s name it “invokePython”  
  7. Okay, cool. Then let’s create one Java File (Class) as our package, let’s name it “PythonPackage”. The purpose of this is to register our Java Module to React Package and register the ReactPackage with React Native.
  8. Okay… we successfully created our package and registered our modules, then let’s expose this package to the host, in this case MainApplication.java.
    As you can see, I added PythonPackage inside of our React Native host.

    Wow… we successfully created our module. But we haven’t finished yet.

  9. Then let’s try invoke your NativeModules inside of the Javascript file but don’t forget to clean your gradle and cache. Modify your javascript file like the code below. Sometimes it’s not linked in the first try. But no problem, we can try it once more, right?

    If it’s successful, you can see Toast gonna appear in your app.
    Are we finished already? Not yet. Remember that we want to inject our Python script. So let’s get going!
  10. If you are aware of your project structure, because of our step in Source set, you generated a new folder named “python”. In this folder you can add a python file.
  11. Let’s create a simple python script and name it script.py which in this case is a Python file extension.
  12. Let’s edit your module (PythonModules.java) like the code below.
    In the code below I wrote my class name: “PythonModule”. But in your case, keep using “PythonModules”.


    As you can see, you need to invoke the getInstance() method that inherits from Python Class. This method always returns the same object. If start() has not yet been called, it will be called with a new GenericPlatform.
    You need to invoke getModule(“${your_script_name}”) method to access your file and this method inherits from PyObject. You can put the “getModule()” method inside of your function or inside of your class.
    If you remember, we create a function called “main” inside of our python script and we accept arguments as parameters. Then we can call it with the “callAttr()” method.

Wow… finally we are done now. Let’s try it!

Is your coffee ruined already? 

Here is what my final project looks like:

 

Note:

  1. If you need a lot of dependencies from Python, better use Python from the backend side instead, because this is gonna make your project size big.
  2. You can install the opencv library but in the same cases probably you can’t use the method that you’re usually using for Desktop purposes. For example: you won’t be able to access the opencv camera because it is running in a different environment.
  3. Even though it’s already open source now, it’s not free, so there will be some limitations in your project. You can remove the limit by adding the license.

Then add your Chaquopy license.

  1. You can create a simple Python compiler or interpreter with Chaquopy.
  2. Here is a project example of React Native with Python and such as bridge implementations

Dodaj komentarz