We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
child_process提供生成子进程的能力,主要基于起spawn方法,官方示例:
const { spawn } = require('child_process'); const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); ls.stderr.on('data', (data) => { console.error(`stderr: ${data}`); }); ls.on('close', (code) => { console.log(`child process exited with code ${code}`); });
默认情况下,上面的stdin、stdout和stderr的管道在父node.js进程和派生的子进程之间建立。这些管道具有有限的(和特定于平台的)容量。如果子进程在未捕获输出的情况下向stdout写入的数据超过了该限制,则子进程将阻止等待管道缓冲区接受更多数据。这与管壳中管道的行为相同。如果输出不会被使用,请使用{stdio:'ignore'}选项。
其中,options可选参数为:
例子:
const exec = require('child_process').exec; exec('node -v', (error, stdout, stderr) => { if(error) { console.error('error: ' + error); return; } console.log('stdout: ' + stdout); console.log('stderr: ' + typeof stderr); });
const execFile = require('child_process').execFile; execFile('node', ['-v'], (error, stdout, stderr) => { if(error) { console.error('error: ' + error); return; } console.log('stdout: ' + stdout); console.log('stderr: ' + typeof stderr); });
输出结果和上面的exec例子一模一样,只是在于是否创建了shell。
modulePath:子进程运行的模块。 args参数说明:
silent
var child_process = require('child_process'); // 例子一:会打印出 output from the child // 默认情况,silent 为 false,子进程的 stdout 等 // 从父进程继承 child_process.fork('./child.js', { silent: false }); // 例子二:不会打印出 output from the silent child // silent 为 true,子进程的 stdout 等 // pipe 向父进程 child_process.fork('./silentChild.js', { silent: true }); // 例子三:打印出 output from another silent child var child = child_process.fork('./anotherSilentChild.js', { silent: true }); child.stdout.setEncoding('utf8'); child.stdout.on('data', function(data){ console.log(data); });
console.log('output from the child');
console.log('output from the silent child');
console.log('output from another silent child');
结果是:
说明:
IPC进程间通信
var child_process = require('child_process'); var child = child_process.fork('./child.js'); child.on('message', function(m){ console.log('message from child: ' + JSON.stringify(m)); }); child.send({from: 'parent'});
process.on('message', function(m){ console.log('message from parent: ' + JSON.stringify(m)); }); process.send({from: 'child'});
运行结果:
message from child: {"from":"child"} message from parent: {"from":"parent"}
execArgv 设置execArgv的目的一般在于,让子进程跟父进程保持相同的执行环境。 比如,父进程指定了--harmony,如果子进程没有指定,那么就要跪了。
options参数说明:
var spawn = require('child_process').spawn; var ls = spawn('ls', ['-al'], { stdio: 'inherit' }); ls.on('close', function(code){ console.log('child exists with code: ' + code); });
var spawn = require('child_process').spawn; // 运行 echo "hello nodejs" | wc var ls = spawn('bash', ['-c', 'echo "hello nodejs" | wc'], { stdio: 'inherit', shell: true }); ls.on('close', function(code){ console.log('child exists with code: ' + code); });
场景1:命令本身不存在,创建子进程报错。 场景2:命令存在,但运行过程报错。
// 场景1 child.on('error', (err) => {... // 场景2 child2.stderr.on('data'...
首先,exec() 内部调用 execFile() 来实现,而 execFile() 内部调用 spawn() 来实现。
exec() -> execFile() -> spawn() 其次,execFile() 内部默认将 options.shell 设置为false,exec() 默认不是false。
ChildProcess 实例注册的事件有 error,close,message
每一个子进程都会得到三个标准的输入输出流,我们可以通过 child.stdin,child.stdout 和 child.stderr 进入。
当那些流关闭之后,使用他们的子进程将会触发 close 事件。这个 close 事件和 exit 事件不同,因为多个子进程可能共享相同的 stdio 流,因此一个子进程退出不代表流关闭了。
// 主进程中 child.stdout.on('data', (data) => { console.log(`child stdout: ${data}`) }); child.stderr.on('data', (data) => { console.error(`stderror ${data}`); });
可以将密集计算的逻辑放到单独的js文件中,然后再通过fork的方式来计算,等计算完成时再通知主进程计算结果,这样避免主进程繁忙的情况了。
const longComputation = () => { let sum = 0; for (let i = 0; i < 1e10; i++) { sum += i; }; return sum; }; process.on('message', (msg) => { const sum = longComputation(); process.send(sum); });
const http = require('http'); const { fork } = require('child_process'); const server = http.createServer(); server.on('request', (req, res) => { if (req.url === '/compute') { const compute = fork('compute.js'); compute.send('start'); compute.on('message', sum => { res.end(`Sum is ${sum}`); }); } else { res.end('Ok') } }); server.listen(3000);
调用child.unref(),将子进程从父进程的事件循环中剔除。于是父进程可以愉快的退出。这里有几个要点
调用child.unref() 设置detached为true 设置stdio为ignore(这点容易忘)
var child_process = require('child_process'); var child = child_process.spawn('node', ['child.js'], { detached: true, stdio: 'ignore' // 备注:如果不置为 ignore,那么 父进程还是不会退出 // stdio: 'inherit' }); child.unref();
SIGINT:interrupt,程序终止信号,通常在用户按下CTRL+C时发出,用来通知前台进程终止进程。 SIGTERM:terminate,程序结束信号,该信号可以被阻塞和处理,通常用来要求程序自己正常退出。shell命令kill缺省产生这个信号。如果信号终止不了,我们才会尝试SIGKILL(强制终止)。
问题的原因是python安装第三方包是通过全局安装的(即sudo安装),在运行时会通过全局的PYTHONPATH去搜索import到的这些第三方包,node是通过process.env加载环境变量的,有可能少了python运行需要的路径(一般node都是$用户启动,而不是#根用户启动),故需要在运行时手动添加上去:
const ls = spawn('python', ['test.py','-u', 'xxx'], { timeout: 10000, env: Object.assign({}, process.env, {PYTHONPATH: '/xxx/lib/python2.7/site-packages'}) });
这样,python通过node开启的子进程运行时就找得到它内部引用的第三方包了。
python一般通过pip(类似于npm)装包到具体包版本下的site-packages下,所以要引用到这个目录下的包,必须得把它的路径暴露给全局的环境变量
问题查询集合: Python 模块搜索路径 Node.js child_process execution of Python script causing errors importing modules Python won't find installed module when run as child process within Electron app
child_process Node.js child_process模块解读
The text was updated successfully, but these errors were encountered:
No branches or pull requests
简介
child_process提供生成子进程的能力,主要基于起spawn方法,官方示例:
默认情况下,上面的stdin、stdout和stderr的管道在父node.js进程和派生的子进程之间建立。这些管道具有有限的(和特定于平台的)容量。如果子进程在未捕获输出的情况下向stdout写入的数据超过了该限制,则子进程将阻止等待管道缓冲区接受更多数据。这与管壳中管道的行为相同。如果输出不会被使用,请使用{stdio:'ignore'}选项。
创建子进程的方式
child_process.exec(command[, options][, callback])
其中,options可选参数为:
例子:
child_process.execFile(file[, args][, options][, callback])
输出结果和上面的exec例子一模一样,只是在于是否创建了shell。
child_process.fork(modulePath[, args][, options])
modulePath:子进程运行的模块。
args参数说明:
fork实例
silent
parent.js
child.js
silentChild.js
anotherSilentChild.js
结果是:
说明:
IPC进程间通信
运行结果:
execArgv
设置execArgv的目的一般在于,让子进程跟父进程保持相同的执行环境。
比如,父进程指定了--harmony,如果子进程没有指定,那么就要跪了。
child_process.spawn(command[, args][, options])
options参数说明:
错误处理,包含两种场景,这两种场景有不同的处理方式。
exec()与execFile()之间的区别
首先,exec() 内部调用 execFile() 来实现,而 execFile() 内部调用 spawn() 来实现。
事件
ChildProcess 实例注册的事件有 error,close,message
每一个子进程都会得到三个标准的输入输出流,我们可以通过 child.stdin,child.stdout 和 child.stderr 进入。
当那些流关闭之后,使用他们的子进程将会触发 close 事件。这个 close 事件和 exit 事件不同,因为多个子进程可能共享相同的 stdio 流,因此一个子进程退出不代表流关闭了。
示例
可以将密集计算的逻辑放到单独的js文件中,然后再通过fork的方式来计算,等计算完成时再通知主进程计算结果,这样避免主进程繁忙的情况了。
compute.js
index.js
通过child.unref()让父进程退出(动态创建守护进程的方式)
调用child.unref(),将子进程从父进程的事件循环中剔除。于是父进程可以愉快的退出。这里有几个要点
信号
SIGINT:interrupt,程序终止信号,通常在用户按下CTRL+C时发出,用来通知前台进程终止进程。
SIGTERM:terminate,程序结束信号,该信号可以被阻塞和处理,通常用来要求程序自己正常退出。shell命令kill缺省产生这个信号。如果信号终止不了,我们才会尝试SIGKILL(强制终止)。
spawn执行python脚本报“ImportError: No module named pandas”
问题的原因是python安装第三方包是通过全局安装的(即sudo安装),在运行时会通过全局的PYTHONPATH去搜索import到的这些第三方包,node是通过process.env加载环境变量的,有可能少了python运行需要的路径(一般node都是$用户启动,而不是#根用户启动),故需要在运行时手动添加上去:
这样,python通过node开启的子进程运行时就找得到它内部引用的第三方包了。
问题查询集合:
Python 模块搜索路径
Node.js child_process execution of Python script causing errors importing modules
Python won't find installed module when run as child process within Electron app
参考
child_process
Node.js child_process模块解读
The text was updated successfully, but these errors were encountered: