1.0.5 • Published 2 years ago

pycore v1.0.5

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

PyCore

PyCore是为NodeJs开发的模块,通过PyCore您可以轻松实现JavaScript与Python的交互,充分利用libuv线程池以及异步特性提高开发和执行的效率。JavaScript可以同步或异步执行Python语句和调用Python函数;在Python中同样可以执行JavaScript语句和调用JavaScript的函数。PyCore主要是为了将HTML+CSS+JavaScript/vuejs等前端技术作为Python程序的界面,PyCore可以将Python和Electron结合,通过Python直接与网页DOM元素进行交互,另外在nodejs中进行开发时可以用python来定制异步多线程操作。

一、Nodejs与python交互的方案

在nodejs中调用python有多种方法,一是使用childprocess通过进程通信就可以实现,这种方式适合简单的操作并不适合复杂的交互;二是采用网络编程,python开启服务器然后在nodejs中请求数据,如果是使用http服务器将不能实现全双工通信,采用websoket可以全双工通信但相对复杂而且需要保持连接,浏览器限制websoket通道数量。网络编程虽然可以实现数据交换,但是实际上效率并不高且占用网络资源和端口。

PyCore整合nodejs和python,在底层上cpython解释器与JavaScript引擎直接交互,这种交互方式能够提高执行效率还非常可靠,经测试通过PyCore创建百万级异步操作仍然可以轻松执行。

二、扩展异步操作

JavaScript是单线程执行,因此当CPU密集型操作时会阻塞主线程执行,JavaScript引入异步执行的操作,将密集型操作分交给其他线程来执行,执行完毕后再将结果返回给JavaScript主线程。异步多线程执行大大提高了单线程执行效率,浏览器中JavaScript可以将网络请求交给浏览器来做,异步线程操作的内容相对比较固定。PyCore引入Python后,JavaScript将可以把密集型操作交给异步独立线程的Python来操作,执行完毕后再将结果返回给JavaScript主线程。

三、跨平台

PyCore目前支持的主流操作系统和CPU架构。

  • windows: x86 / x64
  • linux: x64 / ARM64
  • macos: x64

四、Python版本

当前仅支持Python3.10版本,后续将增加其他版本。

五、使用

(一)安装

npm install pycore

安装pycore模块

(二)引用

const pycore = require('pycore');

加载使用pycore

(三)、函数与参数

1.在JavaScript中调用的函数

模块函数参数说明
init()JSON解释器初始化函数
import()stringimport用python模块名创建对象
import('app').callSyncstring, array模块对象同步调用python函数
import('app').callstring, array, function,function模块对象异步调用python函数
runScriptSync()string同步执行python语句
runScript()string异步执行python语句
release()释放解释器

2.Python中调用Pycore模块函数

模块函数参数说明
pycore.callJStarget='函数名', args=()调用JS函数
pycore.runScriptstring执行JS语句

(三)初始化

PyCore在使用前必须初始化解释器,通过添加python的环境路径,虚拟环境路径以及项目python脚本目录等路径到PyCore中,cpython解释器初始化环境才能够执行python语句和调用函数。

pycore.init({
  "python_version":"3.10",
  "python_home":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
  "program_name":"python",
  "base_prefix":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
  "base_exec_prefix":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
  "base_executable":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6/python.exe",
  "prefix":"pyscript/venv",
  "exec_prefix":"pyscript/venv",
  "executable":"pyscript/venv/Scripts/python.exe",
  "pythonpath_env":"pyscript/venv/Lib/site-packages",
  "module_search_paths":["./", "pyscript"],
  "encoding":"utf-8"
});

字段说明

字段说明
python_versionPython使用的版本
python_homePython安装目录
program_namepython主程序名,windows是python,linux和macos系统python为2.7版本,python3为3.X版本
base_prefixPython安装目录
base_exec_prefixPython安装目录
base_executablepython主程序绝对路径
prefix虚拟环境目录,当不使用虚拟环境则设置为base_prefix
exec_prefix虚拟环境目录,当不使用虚拟环境则设置为base_exec_prefix
executable虚拟环境目录python主程序绝对路径,当不使用虚拟环境则设置为base_executable
pythonpath_env虚拟环境模块目录
module_search_paths搜索模块的路径
encoding解释器编码,一般默认utf-8即可

(四)释放

pycore被初始化后在结束程序是需要使用release释放,当使用node程序执行js文件时,执行完毕后进程不会结束必须使用release()释放结束。electron中初始化pycore跟随主进程结束。

六、依赖动态库

  • windows

pycore必须要python安装目录下的python3.dllpython310.dll,程序搜索动态库的目录有:程序当前目录、path环境变量的路径目录,system32目录,windows目录。如果python为默认安装安装目录已经添加在path环境变量中这可以直接启动程序,否则可以考虑将python3.dll/python310.dll文件拷贝到nodejs项目目录

  • linux

linux系统需要libpython3.10.so.1.0动态库,系统直接安装的python动态库一般在/usr/lib/python3.10/config-3.10-x86_64-linux-gnu目录下,如果是conda或者pyenv安装的python则在其对应目录下。pycore隐式加载动态库,搜索路径为程序当前目录(nodejs项目为项目目录),从/etc/ld.so.cache文件中的路径搜索。/etc/ld.so.cache实际上是一个缓存文件,它由/etc/ld.so.conf.d目录下的所有文件生成,如果要添加新的动态库搜索路径,可以在该目录下创建.conf后缀文件(名称任意),在文件内添加路径后执行ldconfig命令就可以更新/etc/ld.so.cache,动态库搜索路径就生效了。可以直接将libpython3.10.so.1.0动态库拷贝到nodejs项目目录

  • macos

macos必须libpython3.10.dylib动态库,如果是conda或者pyenv安装的python则在其对应目录下找动态库,如果安装官方的python安装包,其路径为/Library/Frameworks/Python.framework/Versions/3.10/lib

因为python版本比较多,目前pycore仅针对python3.10进行开发,如果机器没有python3.10,建议是将python3.10免安装版与nodejs项目集成,或者使用pyenv安装python3.10

七、DOM元素

PyCore在electron中可以操作渲染器的DOM元素,pycore是nodejs模块,在electron中使用要么electron开启集成node环境,要么在preload中预加载pycore模块然后暴露API给渲染器JS使用。不管哪种方式他们都是共享window全局对象,所以都可以对DOM进行操作。

八、案例

github

https://github.com/supercoderlee/pycore-quick-start

index.js

const pycore = require('pycore')

// PyCore初始化
// 根据本机器的python3.10安装路径来配置环境
pycore.init({
    "python_version":"3.10",
    "python_home":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
    "program_name":"python",
    "base_prefix":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
    "base_exec_prefix":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6",
    "base_executable":"C:/Users/Admin/.pyenv/pyenv-win/versions/3.10.6/python.exe",
    "prefix":"pyscript/venv",
    "exec_prefix":"pyscript/venv",
    "executable":"pyscript/venv/Scripts/python.exe",
    "pythonpath_env":"pyscript/venv/Lib/site-packages",
    "module_search_paths":["./", "pyscript"],
    "encoding":"utf-8"
});

// Python调用的JS函数
// 必须是name = function(){}或者name = () => {}方式定义函数,否则无法在Python调用
sayHello = function (num1, num2) {
    let total = num1 + num2;
    console.log('Main SayHello total:' + total);
    return ++total;
}

// 执行Python语句
pycore.runScriptSync("print('main run pyscript')");
pycore.runScript("print('main run pyscript')");

// 创建Python模块对象
const pyApp = pycore.import('app');

// 同步调用Python函数
let res = pyApp.callSync('sum', [1, 9]);
console.log(res);

// 异步调用Python函数
pyApp.call('callJS', [2, 6],
    function (data) {
        console.log(data);
    },
    function (error) {
        console.log(error);
    }
);

pyapp.py

import pycore

def sum(num1, num2):
    return num1 + num2

def callBack(data):
    pycore.runScript("console.log('callBack data:" + str(data) + "');")
    return data # 该函数return返回值,在JS中为空的JS回调函数接收,将不会有任何操作

def callJS(num1, num2):
    state = pycore.callJS(target='sayHello', args=(num1, num2), callback=(__name__, 'callBack')) # 返回0表示失败,1为成功
    return num1 + num2
1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago