2016-11-24 6 views
1

私はpythonサブプロセスを開始し、stdoutを読み込むnode.jsスクリプトを持っています。これは、pythonプロセスがstdinからの読み込みを試みない限り機能します。親プロセスは子プロセスから何も取得しません。Node.jsはstdinから読み込んだときにpythonサブプロセスstdoutを読み取ることができません

私はここにNode.jsのスクリプトと2 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( 'before'、flush = True)'を実行することができます。その後、データを待っています。まあ...データを送信する必要があります。 – tdelaney

+0

'flush = True'トリックが問題を解決しました。これを回答として投稿すると私はそれを受け入れるでしょう:) – Martin

+0

これを 'node.js'側で' const spawn = require( 'pty.js')。spawn; 'のようなもので修正する方が良いかもしれません。 stdout/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文を使用してか、あなたはまた、基本的にはユーザーに表示されるという考えにプログラムをだまして、端末をエミュレートすることにより、Node.jsの側にそれを修正することができsys.stdoutオブジェクト自体

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

でこれを行うことができます。

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

これはより一般的です。子供の協力を必要としません。しかし、それは複雑になる可能性があります。いくつかの子プロセスは、添付されたttyに関する情報を得て、メニューの作成やカラー出力のようなもっと複雑な作業を行います。しかし、それはしばしば素晴らしい選択です。

+0

あなたの答えをありがとう。 ptyソリューションは機能しますが、最初のアイデアをもう一度見てみたいと思います。私がstdoutをフラッシュすると、私はpythonから出力を受け取ることができますが、別の問題があります: 'client.stdin.write( 'test')を使って子プロセスにテキストを送ると、これはpythonプログラムには現れません。私はどういうわけか 'stdin'も同様にフラッシュする必要がありますか? – Martin

+0

そうだと思います。私はnode.jsを本当に知っていませんが、spawnが子stdinへのパイプを設定すると、そのブロックはバッファされ、同じ問題があります。あなたは行を読むので、改行を入れる必要もあります。 – tdelaney

+0

改行がトリックでした。私自身はこれを考えていたはずです... – Martin

関連する問題