写点什么

Boa: 在 Node.js 中使用 Python

  • 2020-04-21
  • 本文字数:3072 字

    阅读完需:约 10 分钟

Boa: 在 Node.js 中使用 Python

Hello,大家好,有一段时间不见了。


这次主要给大家带来一个好东西,它的主要用途就是能让大家在 Node.js 中使用 Python 的接口和函数。可能你看到这里会好奇,会疑惑,会不解,我 Node.js 大法那么好,干嘛要用 Python 呢?如果你之前尝试了解过一些机器学习的 JavaScript 的应用,就会比较清楚这背后的原因。


现状是机器学习生态几乎是捆绑在 Python 这门语言在高速迭代着的,而 JavaScript 只能望其项背,如果我们期望从零做到 Python 如今的规模,需要付出的工作量是巨大的,这个我在几年前写了 tensorflow-nodejs 的时候,就已经这么觉得了。


所以,我们就必须换一个思路,既然无法超越你,那么就利用你。对于脚本语言的开发者来说,其实并不在意底层是如何实现的,只要上层的语言和接口是我熟悉的就好,因此 Boa 就是为此而诞生的一个 Node.js 库,它通过桥接 CPython 来让 JavaScript 具备访问 Python 生态的能力,另外又借助于 ES6 新特性,来为使用者提供无缝的开发体验,那么到底是如何的体验呢?


下面来看一个简单的例子:


const boa = require('@pipcook/boa');const os = boa.import('os');console.log(os.getpid()); // prints the pid from python.
// using keyword arguments namely `kwargs`os.makedirs('..', boa.kwargs({ mode: 0x777, exist_ok: false,}));
// using bult-in functionsconst { range, len } = boa.builtins();const list = range(0, 10); // create a range arrayconsole.log(len(list)); // 10console.log(list[2]); // 2
复制代码


是不是很简单呢,只需要通过 boa.import 将 Python 的对象加载进来后,剩下的对象访问、函数调用以及数组访问都与我们使用 JavaScript 毫无区别。


const boa = require('@pipcook/boa');const { len, tuple, enumerate } = boa.builtins();const torch = boa.import('torch');const torchtext = boa.import('torchtext');const { nn, optim } = torch;
class TextSentiment extends nn.Module { constructor(sizeOfVocab, dimOfEmbed, numOfClass) { super(); this.embedding = nn.EmbeddingBag(sizeOfVocab, dimOfEmbed, boa.kwargs({ sparse: true, })); this.fc = nn.Linear(dimOfEmbed, numOfClass); this.init_weights(); } init_weights() { const initrange = 0.5 this.embedding.weight.data.uniform_(-initrange, initrange); this.fc.weight.data.uniform_(-initrange, initrange); this.fc.bias.data.zero_(); } forward(text, offsets) { const embedded = this.embedding(text, offsets); return this.fc(embedded); }}
复制代码


上面的例子除了示例了如何从 JavaScript 中继承自一个 Python 的类之外,还展示了我们如何使用 PyTorch 来创建一个模型,这是不是很 JavaScript 呢?


值得一提的是,在 Boa 的代码中,没有对 PyTorch 做过任何的封装,只要你在本地通过 Python 安装了对应的包就可以像上面的代码一样使用了,所以理论上你可以对任何 Python 包做上面所做的事情。


接下来,我们分别介绍一些主要的方法。

builtins()

Python 会内置一些常用的方法在 builtin 中,具体的 API 列表在:


https://docs.python.org/3.7/library/functions.html


那么 Boa 也提供了对应的方法:


const { len, list, range } = boa.builtins();
复制代码

import(name)

除了内置的方法外,最重要的功能便是加载 Python 包,那么 import 就是做这个事儿的。


const np = boa.import('numpy');
复制代码

kwargs(map)

接下来是 Python 中的关键字参数(Keyword Arguments),在 Python 中,提供了一种使用 Map 的方式来表示参数,如:


foobar(100, x=10, y=20)
复制代码


它能更好地帮助调用者了解每个参数的含义,为此,在 Boa 中增加了 kwargs 方法来支持这种用法:


foobar(100, boa.kwargs({ x: 10, y: 20 }));
复制代码

with(ctx, fn)

With 可能对于一些熟悉 JavaScript 历史的人会比较眼熟,但 Python 中的 with,用法和目的并不与 JavaScript 相同,Python 中的 with 语句有点类似于 JavaScript 中的 Block Scoping:


with(localcontext()) {  # balabala}
复制代码


上面的 Python 代码是将 localcontext() 的状态保存下来,然后开始执行 with 语句中的块代码,最后,将 localcontext() 的状态释放。


内部的实现机制就是每个传到 with 语句中的变量需要实现两个方法:enter 和 exit,然后分别在块代码执行前后调用,因此对于 Boa 中的用法,如下:


boa.with(torch.no_grad(), () => {  const output = model(text, offsets);  const loss = criterion(output, cls);  validLoss += loss.item();  validAcc += boa.eval`(${output.argmax(1)} == ${cls}).sum().item()`;});
复制代码


上面的例子是 PyTorch 中一个普通的计算模型效果的逻辑,首先通过 torch.no_grad() 设置了一个上下文,然后开始执行计算的代码,在块代码执行结束后,会自动将状态恢复。

eval(str)

最后一个要说的,就是动态的执行一些 Python 表达式(单行),为什么要提供这么一个方法呢?这还是要说回 Python 的优势,在一些很复杂的数据处理的场景,往往 Python 表达式还是能非常简单易懂地表达,这样就大大地减少了代码的复杂度,我们先来看一个例子:


const line = (boa.eval`'\t'.join([str(x) for x in ${vec}])`);
复制代码


上面的代码如果要换成 JavaScript 的话:


vec.map(x => x.toString()).join('\t');
复制代码


看着似乎差不多了多少是吧?那么再来看看下面的例子:


boa.eval`{u:i for i, u in enumerate(${vocab})}`;boa.eval`[${char2idx}[c] for c in ${text}]`boa.eval`${chunk}[:-1]`boa.eval`${chunk}[0:-1:2]`
复制代码


怎么样,是否是感觉上面的例子已经没法使用 JavaScript 简单的一行就能搞定了呢?


不过值得一提的是,JavaScript 在这方面也在渐渐地弥补,这里 是整理的一些 TC39 正在做的一些相关的标准,其中就包括上面的 Slice Notation。


说回到 eval 的定位,它像是对 JavaScript 的补充,它在一些标准还未落地和稳定之前,可以让我们使用 Python 表达式来更简单地表达,而所需要的仅仅是一些低成本的学习即可。


接下来就说说 eval 到底如何使用,它接受一个“字符串”,但我们一般在使用时都会通过 Template String,下来先看两个例子:


boa.eval('print("foobar")');boa.eval(`print("${txt}")`);
复制代码


看完上面两行代码,它们是比较少见的用法。真正常用,也是最能发挥出 eval 效果的是使用 Tagged Template String,这种用法就像我们一开始看到的一样,在 eval 后面直接跟模版字符串的内容,这样做的好处是 eval 函数会接收到所有的模版参数,这样我们便可以将 JavaScript 的对象和 Python 表达式打通,实现更平滑的使用体验,如下:


const chunk = range(0, 10);boa.eval`${chunk}[0:-1:2]`
复制代码


上面就是把 chunk 传到了表达式中,再通过 Python 的 Slice Notation 语法去取到对应的值,最后返回到 JavaScript 的世界中。

尾声

好了,简单的 API 介绍就先到这里,如果想了解更多 API 和 Boa 的能力,可以到 Boa 的文档了解:


https://github.com/alibaba/pipcook/blob/master/docs/tutorials/want-to-use-python.md


另外,Boa 作为 Pipcook 的一个子项目,也非常欢迎大家来加入进来,对于想加入的同学可以通过这些 Issue 作为不错的开始:


https://github.com/alibaba/pipcook/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22


最后再说一下 Boa 的初衷,就是希望能让 Node.js 开发者更无缝地使用 Python 中丰富的机器学习生态。可以说,从今天开始,你就可以开始看着 Python 的文档,使用 JavaScript 来“学习和使用”机器学习和深度学习了!


2020-04-21 15:532862

评论 1 条评论

发布
用户头像
「望其项背」一般以否定句式使用
2020-04-22 10:44
回复
没有更多了
发现更多内容

【JavaWeb】Servlet系列——请求和响应过程的角色和协议、模拟Servlet本质、开发第一个带有Servlet的Webapp、关于Java EE的版本

胖虎不秃头

Web java; 9月月更

【JavaWeb】Servlet系列——响应HTML代码、Servlet连接数据库、IDEA开发Servlet程序、Servlet对象的生命周期、Generic

胖虎不秃头

Web java; 9月月更

干货分享!JAVA诊断工具Arthas在Rainbond上实践~

北京好雨科技有限公司

Kubernetes Arthas 企业号九月金秋榜

web前端培训班口碑哪个比较好

小谷哥

软件测试 | 测试开发 | Kafka入门

测吧(北京)科技有限公司

kafka 软件测试

SpringBoot源码 | printBanner方法解析

六月的雨在InfoQ

源码 springboot 9月月更 springboot源码

Java 在Word文档中添加艺术字

在下毛毛雨

Java word 添加艺术字

从数据库发展史看数据库未来技术趋势

OceanBase 数据库

利用京东云Web应用防火墙实现Web入侵防护

京东科技开发者

网络安全 安全 防火墙 WEB安全 京东云

Maven的下载安装配置以及IDAEA中Maven的配置

守夜人st

9月月更

深圳参加java培训哪个机构靠谱

小谷哥

数字藏品电商平台开发:如何开发数字藏品?

开源直播系统源码

区块链 NFT 数字藏品 数字藏品系统 数字藏品软件

【DBA100人】胡中豪:国产分布式数据库DBA炼成记

OceanBase 数据库

Java注解详细

石臻臻的杂货铺

Java 阅读 9月月更

OpenHarmony——内核IPC机制数据结构解析

OpenHarmony开发者

OpenHarmony

清远市等保测评公司有几家?分别在哪里?

行云管家

网络安全 等保 等保测评 等级测评 清远

java开发培训好还是自学好?

小谷哥

软件测试 | 测试开发 | 基于php-code-coverage的增量代码覆盖率实现

测吧(北京)科技有限公司

php 测试 PHP框架

Spring源码解析(十二)Spring扩展接口SmartInstantiationAwareBeanPostProcessor解析

石臻臻的杂货铺

spring 9月月更

数据如何指导决策:优酷主客APP播转率的C端优化

阿里巴巴文娱技术

数据分析 数据 BI

启科量子公布量子计算机工程化进展

启科量子开发者官方号

在北京如何能找到大数据培训机构

小谷哥

软件测试 | 测试开发 | 使用charles 修改服务器返回数据

测吧(北京)科技有限公司

软件测试 测试

软件测试 | 测试开发 | 测试人生 | 拿到多个 offer 从了一线互联网公司并涨薪70%,90后小哥哥免费分享面试经验~

测吧(北京)科技有限公司

测试 软件测试和开发

切流的基本逻辑

agnostic

切流

上海参加java开发培训怎么样

小谷哥

软件测试 | 测试开发 | vue双向绑定原理实现

测吧(北京)科技有限公司

Vue 测试框架

软件测试 | 测试开发 | 测试人生 | 毕业2年,拒绝独角兽入职名企大厂涨薪10万+,这个95后小姐姐好飒

测吧(北京)科技有限公司

软件测试 测试

软件测试 | 测试开发 | 测试人生 | 从传统行业到名企大厂,薪资翻倍,我做到了

测吧(北京)科技有限公司

面试 测试工程师 软件测试和开发

【JavaWeb】Servlet系列——模板方法设计模式、HttpServlet源码分析、Web站点的欢迎页面、关于WEB-INF目录

胖虎不秃头

Web java; 9月月更

2022 DEMO CHINA创新中国峰会拉开帷幕

创业邦

Boa: 在 Node.js 中使用 Python_大前端_徐明强_InfoQ精选文章