【问题标题】:How to interactively communicate with a python3 programme from a node one?如何从节点一与 python3 程序进行交互通信?
【发布时间】:2017-01-23 17:20:26
【问题描述】:

我有以下“机器人”python 脚本:

#! /usr/bin/env python3
import asyncio
import sys


def callback(*args):
    data = sys.stdin.readline()[:-1]
    print('ECHO: {}'.format(data), flush=True)
    if data == 'EOF':
        loop.stop()

print('Bot spawning!')
loop = asyncio.get_event_loop()
task = loop.add_reader(sys.stdin.fileno(), callback)
loop.run_forever()
loop.close()
print('Bot dead')

应该由这个节点应用程序处理:

#! /usr/bin/env node
const createInterface = require('readline').createInterface
const spawn = require('child_process').spawn

const lines = [
  'I',
  'LOVE',
  'DEAD',
  'BEEF',
  'EOF',
]
const bot = spawn('./poc.py')
const rl = createInterface({
  input: bot.stdout,
})
rl.on('line', line => {
  console.log('BOT SAYS', new Array(line))
})
// bot.stdout.on('data', data => {
//     console.log(`BOT SAYS: ${data}`)
// })

bot.stdin.on('error', (err) => console.log(err))

try {
  console.log('Dispatching lines...')
  lines.forEach( line => {
    console.log('Connected', bot.connected)
    console.log('Sending', line)
    bot.stdin.write(`${line}\n`)
  })
}
finally {
  // bot.stdin.end()
}

问题是,除非我取消注释 bot.stdin.end() 行,否则我不会从机器人获得任何输出(在几次运行中,我得到了两行,但不是全部)。

我尝试了不同的方法,例如直接从 bot.stdout 读取,或者在 python 程序中显式刷新缓冲区,或者使用 execFile 而不是 spawn...但都无济于事。

所以我的问题是:如何让节点程序通过stdinstdout 与另一个进程进行交互通信,而不必关闭管道或等待所述进程的执行完成?

也许我应该采用完全不同的方法?

编辑:在我的 Fedora 25 工作站上运行上述代码会导致以下输出和程序不确定地挂起:

[] % ./poc.js  
Dispatching lines...
Connected false
Sending I
Connected false
Sending LOVE
Connected false
Sending DEAD
Connected false
Sending BEEF
Connected false
Sending EOF
BOT SAYS [ 'Bot spawning!' ]
BOT SAYS [ 'ECHO: I' ]

请注意,子进程bot 一直处于断开状态,但仍然处理了两行输入...

【问题讨论】:

    标签: python node.js pipe python-3.5


    【解决方案1】:

    我认为问题不在于您的机器人如何编写其输出,而在于它如何处理其输入。

    asyncio 注意到输入流中有数据,并调用回调,但回调并没有处理所有可用的输入。回调不再被调用,因为从那以后流没有改变,并且剩余的输入可能保存在缓冲区中,等待。

    我想你会希望你的回调处理任何输入,直到它不能再获取,然后再返回。

    【讨论】:

    • 我会在有时间的时候尝试一下(可能今晚在家里)。感谢您现在的建议! :)
    猜你喜欢
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 2014-06-05
    相关资源
    最近更新 更多