You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native中运行Python脚本?需本地端解决方案

在React Native本地运行Python脚本(打包为.so方案)

核心逻辑

要在React Native本地执行Python脚本,你可以通过将Python代码编译为原生共享库(.so),再通过React Native原生桥接调用。这种方案完全本地运行,无需依赖服务器API。下面是具体实现步骤和代码示例:


步骤1:将Python脚本编译为.so文件

这里用Cython实现Python到C的编译,再交叉编译为Android兼容的.so(iOS可编译为.framework,逻辑类似)。

准备工作

  1. 安装Cython:pip install cython
  2. 配置Android NDK环境(用于交叉编译Android架构的.so)

示例代码

假设你的Python后处理脚本post_process.py内容如下:

def process_data(input_data):
    # 你的后处理逻辑,比如数据过滤、计算
    result = [x * 2 for x in input_data]
    return result

编写setup.py用于编译:

from setuptools import setup
from Cython.Build import cythonize
import os

# 针对Android交叉编译的配置(需替换为你的NDK路径和目标ABI)
ndk_path = "/path/to/your/android-ndk"
target_arch = "arm64-v8a"
os.environ["CC"] = f"{ndk_path}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang"
os.environ["CXX"] = f"{ndk_path}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++"

setup(
    name="PostProcess",
    ext_modules=cythonize("post_process.py"),
    zip_safe=False,
)

编译命令

执行以下命令生成.so文件:

python setup.py build_ext --inplace

编译完成后,会在当前目录生成post_process.so(对应arm64-v8a架构,如需其他ABI,修改target_arch重新编译)。


步骤2:React Native集成.so并编写原生模块

Android端集成

  1. 将编译好的.so文件放到android/app/src/main/jniLibs/arm64-v8a/(其他ABI对应目录同理)。
  2. 编写Kotlin原生模块,加载.so并暴露方法给React Native:
package com.yourappname

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.WritableNativeArray

class PythonProcessModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    // 加载.so库
    init {
        System.loadLibrary("post_process")
    }

    // 声明native方法(对应Cython编译后的函数)
    external fun processData(input: List<Int>): List<Int>

    override fun getName(): String {
        return "PythonProcessModule"
    }

    @ReactMethod
    fun processDataFromRN(input: ReadableArray, promise: com.facebook.react.bridge.Promise) {
        try {
            val inputList = mutableListOf<Int>()
            for (i in 0 until input.size()) {
                inputList.add(input.getInt(i))
            }
            val result = processData(inputList)
            val writableArray = WritableNativeArray()
            result.forEach { writableArray.pushInt(it) }
            promise.resolve(writableArray)
        } catch (e: Exception) {
            promise.reject("PROCESS_ERROR", e.message)
        }
    }
}
  1. 注册原生模块:在MainApplication.kt中添加模块到ReactPackage:
override fun getPackages(): List<ReactPackage> {
    return PackageList(this).packages.apply {
        add(object : ReactPackage {
            override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
                return listOf(PythonProcessModule(reactContext))
            }

            override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
                return emptyList()
            }
        })
    }
}

步骤3:远程下载.so并动态加载

如果需要从远程下载.so文件(而不是打包进APK),需要处理文件下载和动态加载:

React Native端下载示例

import { Platform, PermissionsAndroid } from 'react-native';
import RNFetchBlob from 'react-native-fetch-blob'; // 需安装:npm install react-native-fetch-blob

const downloadAndLoadSo = async () => {
    // Android申请存储权限
    if (Platform.OS === 'android') {
        const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
            {
                title: "存储权限申请",
                message: "需要存储权限下载.so文件",
            }
        );
        if (granted !== PermissionsAndroid.RESULTS.GRANTED) return;
    }

    // 下载.so文件到应用私有目录
    const dirs = RNFetchBlob.fs.dirs;
    const soPath = `${dirs.DocumentDir}/post_process.so`;
    await RNFetchBlob.config({ path: soPath })
        .fetch('GET', 'https://your-server.com/post_process.so');

    // 调用原生模块加载动态库并执行(需修改原生模块支持动态加载路径)
    NativeModules.PythonProcessModule.loadAndProcess(soPath, [1,2,3], (error, result) => {
        if (error) console.error(error);
        else console.log("处理结果:", result);
    });
};

修改原生模块支持动态加载

在Kotlin模块中添加动态加载方法:

@ReactMethod
fun loadAndProcess(soPath: String, input: ReadableArray, promise: com.facebook.react.bridge.Promise) {
    try {
        // 动态加载指定路径的.so
        System.load(soPath)
        // 执行处理逻辑(同之前的processDataFromRN)
        val inputList = mutableListOf<Int>()
        for (i in 0 until input.size()) {
            inputList.add(input.getInt(i))
        }
        val result = processData(inputList)
        val writableArray = WritableNativeArray()
        result.forEach { writableArray.pushInt(it) }
        promise.resolve(writableArray)
    } catch (e: Exception) {
        promise.reject("LOAD_ERROR", e.message)
    }
}

注意事项

  • ABI兼容性:需为目标设备的CPU架构(如armeabi-v7a、arm64-v8a)编译对应的.so,否则会加载失败。
  • Python依赖:如果脚本依赖第三方库,需确保这些库能被静态编译进.so,否则可能出现运行时依赖缺失。
  • iOS适配:iOS无法直接加载.so,需将Python代码编译为.framework,使用Objective-C/Swift编写原生模块,逻辑与Android类似。

内容的提问来源于stack exchange,提问作者NotFryingNemo74

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:30:56