Python与Javascript相互调用超详细讲解(2022年1月最新)(三)基本原理Part 3 - 通过C/C++联通

目录
首先要明白的是,javascript和python都是解释型语言,它们的运行是需要具体的runtime的。

  • Python: 我们最常安装的Python其实是cpython,它有一个基于C的解释器。除此之外还有像pypy这种解释器,等等。基本上,不使用cpython作为python的runtime的最大问题就是通过pypi安装的那些外来包,甚至有一些cpython自己的原生包(像collections这种)都用不了。
  • JavaScript: 常见的运行引擎有google的V8,Mozilla的SpiderMonkey等等,这些引擎可以把JavaScript代码转换成机器码执行。基于这些基础的运行引擎,我们可以开发支持JS的浏览器(比如Chrome的JS运行引擎就是V8);也可以开发功能更多的JS运行环境,比如Node.js,相当于我们不需要一个浏览器,也可以跑JS代码。有了Node.js,JS包管理也变得方便许多,如果我们想把开发好的Node.js包再给浏览器用,就需要把基于Node.js的源代码编译成浏览器支持的JS代码。

在本文叙述中,假定:

  • 主语言: 最终的主程序所用的语言
  • 副语言: 不是主语言的另一种语言

例如,python调用js,python就是主语言,js是副语言

Python与Javascript相互调用超详细讲解(2022年1月最新)(三)基本原理Part 3 - 通过C/C++联通

TL; DR

个人觉得这是最佳方案了,但是老一点的技术文章几乎没有人说。也可能是前几年javascript的C语言相关的技术还没发展得很全面?

只要选好合适的库,几乎适用于绝大部分场景:

  1. python的各种复杂的包不能割舍,Node.js的各种包也不想割舍。
  2. python和javascript的交互巨频繁,传递的对象也大
  3. 对运行效率有要求:“把javascript变成python之后跑得也太慢了吧!”
  4. 甚至想在主语言里搞多进程并发编程

有库!有库!有库!

python调javascript

  • pyv8pip install -v pyv8
    • 缺点:太!老!了!甚至需要用python 2来构建V8……直接就是一个不建议使用。
  • stpyv8:后人做的pyv8升级,把Python API改成了python3的。
    • 缺点
      • 但V8还是要用python 2构建,虽然你不用再额外装javascript的runtime,但你同时需要python2 和python3的runtime。
      • 由于js runtime是V8,有一些Node特性可能用不了,以及有的Node模块可能需要转换成V8可以识别的js文件(可以参考这里
  • PyMiniRacer:基本跟上面一个项目做的差不多的事情。基于python 3嵌入了V8,但构建V8还是要用python 2。

javascript调python

  • PyNode:也是我最后用的包,安装上会有点小问题,但总体是蛮不错的
    python方要先安装gyp-nextpip install gyp-next,然后npm install @fridgerator/pynode
    • 优点
      1. 上面说的所有优点都可以做到!就算NPM直接安装的包做不到,稍微改改就可以做到。
      2. 和下面的boa相比,非常轻量,只有几十MB,boa有几面MB。
    • 缺点:列得比较多只是因为我最后真的用了它,所以踩过一些坑,有的解决了,有的就还是将就用了。后面我会写个踩坑经验。
      1. 对python特性只有简单的支持。比如:python的关键字参数(kwargs)是不支持的;传一些复杂的object的时候解析得不是很靠谱,例如:有的简单的dict套dict传给javascript明明可以是个object,但它会变成它自己的python对象包装器(PyObjectWrapper),希望以后可以继续维护改进吧。
      2. 由于使用的python C API一直在变化,最好是用python 3.6以上。Node没有太新的版本要求,只要支持N-API就可以了。
      3. 依赖python动态库,在不同OS和Architecture的安装时可能会出现一些找不到库的问题(但应该可以解决!)。
      4. 调用startInterpreter()起2次python解释器的话会有segmentation fault(可以解决!)
  • boanpm install @pipcook/boa。阿里的开源库,跟pynode基本也是同一个原理。如果没有缺点里所说的情况,更推荐用这个
    • 优点
      1. 安装它的时候,会通过miniconda直接安装一个python环境,不需要自己装python且找python的动态库。
      2. 支持更多的python特性,比如关键字参数(kwargs),with语句之类的。
      3. 由于是阿里维护的,可能我们问问题会更方便吧(不是x)
    • 缺点:但由于它装了一个conda的python环境,且只能使用这个python环境,导致损失了一些灵活性。这在大部分情况下应该都不是问题,其实这个库会比pynode更鲁棒一些。主要还是在我的use case里,我还是必需要在我本地的python runtime里执行一些程序的,而boa只能使用conda的python runtime,那么结果就是python部分的依赖的包要么同时在这两个runtime里都装一遍,要么只在一个里装,把site-packages添加到另一个runtime的sys.path下。如果包装在本地runtime里,那么conda的runtime可能要把本地runtime的库目录,以及本地虚拟环境的库目录都加进入,我觉得挺麻烦的。
  • pyodide:没用过,大致看了看介绍。直接把cpython解释器编译成了WebAssembly。
    • 优点:完全不用安装python啦!而且比起js解释器,支持很多python包,包括numpy之类的。感觉非常适合浏览器使用python进行科学计算!
    • 缺点
      • 支持的python包还是有限
      • 跟你本地的cpython不是一个runtime,可能你在本地python调试好的代码在pyodide里会有问题
      • 你的python部分暂时跟并发编程无缘啦!

原理

众所周知(不是x

事就这么成了,让这两种语言通过C语言来联通!这种方式的好处是:

  1. python和javascript实际上都还是在各自的runtime里运行,因此只要你单独在python环境,或者javascript环境开发的代码没问题,连起来也没问题,所以支持各种扩展包。
  2. 而且它们在同一个进程里,我们的开销几乎只有数据类型转换,真正做到了高效率的两种语言的交互

我根据目前见过的项目,总结了一下目前已有的方式:

基于Node.js的javascript调用python

参考:《NodeJS and Python interoperability!》(题外话:才发现就是PyNode项目的作者写的!TQL!)

这篇文章把这条路的基本原理写得很清楚了,我稍微翻译一下大意,尽量达,不信不雅(x)。

从Node调用python函数

NodeJS与Python之间的互操作还是相对简单 可行的。我不是指基于子进程调用CLI以及进程间通信的方式,或者一些其它古怪的方式。这两种语言都是用C/C++编写的,所以通过调用副语言的本机库,互操作是可能的。看看我使用这两种语言的底层API的过程中都经历了什么吧,我可真的很不喜欢这个!

上一篇:docker


下一篇:职责链模式_(行为型)