2016-11-24 93 views
1

我有一個node.js腳本啓動python子流程並讀取它的stdout。只要python進程不嘗試從標準輸入讀取,它就會工作。然後父進程不會從孩子那裏得到任何東西。Node.js讀取標準輸入時無法讀取python子流程stdout

我有node.js的腳本。我們兩個Python測試案例:

第一個孩子(如果你評論說,試圖從標準輸入讀取行這兩個例子中工作):

import sys 

print('before') 

for line in sys.stdin: 
    print(line) 

print('after') 

老二:

import sys 

print('before') 

while True: 
    line = sys.stdin.readline() 

    if line != '': 
     print(line) 
    else: 
     break 

print('after') 

家長:

const spawn = require('child_process').spawn; 

let client = spawn('python', ['test1.py'], {cwd: '/tmp'}); 

client.stdout.on('data', (data) => { 
    console.log(data.toString()); 
}); 

client.stderr.on('data', (data) => { 
    console.log(data.toString()); 
}); 

client.on('close',() => { 
    console.log('close'); 
}); 

client.on('exit',() => { 
    console.log('exit'); 
}); 


client.on('disconnect',() => { 
    console.log('disconnect'); 
}) 
+0

我不知道node.js,但從python的角度來看,一條線被寫入,但由於它是一個管道,而不是一個tty,它被緩衝在等待更多的數據。你可以在''之前執行'print(',flush = True)'立即發送。然後它會等待數據,並且......您需要發送數據。 – tdelaney

+0

'flush = True'技巧確實解決了這個問題。如果你發佈這個答案,我會接受它:) – Martin

+0

這可能是更好的解決這個'node.js'方面像'const spawn = require('pty.js')。spawn;'這個問題討論分裂st​​dout/err流http://stackoverflow.com/questions/15339379/node-js-spawning-a-child-process-interactively-with-separate-stdout-and-stderr-s。我很樂意提供答案......但我不確定它是最好的答案。 – tdelaney

回答

2

進程stdout可以是無緩衝,行緩衝或塊緩衝,具體取決於進程的啓動方式。特別是,從控制檯啓動的程序是行緩衝的,程序的stdout被重定向(到管道或文件)被塊緩衝。這樣做是爲了有效地增加總體程序。人們希望馬上看到事物,所以終端是行緩衝的,但是其他程序和文件可以等待並且在更大的塊中獲得東西,因此它們被塊緩衝。

您可以通過強制數據在每次寫入時被流動化來解決python方面的問題。您可以使用print陳述或與sys.stdout對象本身

print('line 1', flush=True) 
print('line 2') 
print('line 3') 
sys.stdout.flush() 

您還可以通過模擬一個終端,基本上欺騙程序,以爲它是向用戶顯示其固定到Node.js的側做到這一點。

const spawn = require('pty.js').spawn; 

這是更通用 - 你不需要孩子的合作,使其工作。但它可能會變得複雜。一些子進程獲取有關附加tty的信息,以執行更復雜的操作,如創建菜單或顏色輸出。但它經常是一個很好的選擇。

+0

謝謝你的回答。 pty解決方案有效,但我想再看看第一個想法。當我刷新標準輸出時,我可以從python接收輸出,但是我遇到了另一個問題:當我使用'client.stdin.write('test')'將文本發送到子進程時,它不會顯示在python程序中。我還需要刷新'stdin'嗎? – Martin

+0

我這麼認爲。我並不真正瞭解node.js,但是如果spawn爲子標準輸入設置了一個管道,它的塊將被緩衝並且具有相同的問題。由於您正在閱讀各行,因此您還需要添加一個換行符。 – tdelaney

+0

換行符訣竅。應該想到這個我自己... – Martin