在Pyhton中用popen方法调用nodejs执行结果

  • 一、为什么要用popen?
  • 二、使用方法
  • 方法一:os.popen简易传参
  • 1、js文件编辑
  • 2、Python调用
  • 方法二:os.popen导出函数传参
  • 1、js文件编译
  • 2、Python调用
  • 方法三:subprocess.Popen简易传参
  • 1、js文件编译
  • 2、Python调用
  • 三、注意事项


一、为什么要用popen?

在不安装第三方js执行库的情况下,直接用Python原生os或subprocess库来执行js代码不失为一种比较便捷的方法,尤其是js文件比较大的时,直接以字符串形式写在Python代码里通过其他库(execjs等)来执行会显得代码异常臃肿,而且不存在第三方库因为无法正确编译js文件导致执行报错的问题,总之使用popen方法时,只要js代码在nodejs环境里能正常运行,最后用Python调用其结果时基本不会出现异常报错。

二、使用方法

以一个简单的求和运算函数为例,展示如何通过os.popensubprocess.Popen方法获取js代码执行输出结果。

方法一:os.popen简易传参

1、js文件编辑

function add(a, b) {
    return a + b
}
//外部传参设置:对应参数设置方法一,这种方法传过来的参数是字符串形式,如是数值参数,需要额外转换格式
var a = parseInt(process.argv[2]);
var b = parseInt(process.argv[3]);
console.log(add(a,b))

2、Python调用

import os
a=1
b=2
#参数设置方法一,temp为js文件名
command1='node temp {0} {1}'.format(a,b)
with os.popen(command1) as nodejs:
    result= nodejs.read().replace('\n', '')
print(result)

方法二:os.popen导出函数传参

1、js文件编译

function add2(a, b) {
    return a + b
}
//外部传参设置:对应参数设置方法二
module.exports.init = function (arg1, arg2) {
    console.log(add2(arg1, arg2));
};

2、Python调用

import os
a=1
b=2
command2 = 'node -e "require(\\"%s\\").init(%s,%s)"' % ('./os_popen_use.js', a, b)
with os.popen(command2) as nodejs2:
    result2= nodejs2.read().replace('\n', '')
    print(result2)

方法三:subprocess.Popen简易传参

1、js文件编译

function add1(a, b) {
    return a + b
}
//外部传参设置:与方法一相同,如果是字符串计算,则不需要parseInt()函数转换类型
var a = parseInt(process.argv[2]);
var b = parseInt(process.argv[3]);

console.log(add1(a,b));

2、Python调用

import subprocess
a=1
b=2
#使用subprocess模块的Popen方法时,参数可以以数组的形式传递,逻辑比较清晰
# p = subprocess.Popen('node os_popen_use {0} {1}'.format(a,b), stdout=subprocess.PIPE)#也可以设置传递一个长字符串的形式传递参数
p = subprocess.Popen(['node','./os_popen_use.js','1','2'], stdout=subprocess.PIPE)
out = p.stdout.read()
print('out:',out)

输出结果:

out: 3

三、注意事项

在使用os.popen方法时,需要注意python版本问题,尤其是3.8及以上的版本,在使用read()方法读取js执行结果时候很有可能会报错,推测是高版本python默认是byte编码,跟执行结果编码不同,出现编码环境冲突问题。

TypeError: a bytes-like object is required, not 'str'

因此建议在3.8以上版本直接使用subprocess.Popen方法调用js,但需要注意的是通过python调用的js文件返回值最后都会默认加个'\n',也及时空格符,需要手动替换。