2017-09-13 21 views
1

自分自身の出力ストリームを定義することによってsubprocess.callのリアルタイム出力を取得しようとしていますが、動作しないようです。subprocess.call用のカスタム出力ストリームを作成する方法

理由:私は、サブプロセスを実行し、(私はスクリプトを見て、現在の進行状況を見ることができるようにリアルタイムで)ファイル

サブプロセスにそれをログに記録するだけでなく、両方のstdoutにその呼び出しの出力を取得したいです。 PY:

import time 

while True: 
    print("Things") 
    time.sleep(1) 

mainprocess.py

import subprocess 
import io 

class CustomIO(io.IOBase): 
    def write(self, str): 
     print("CustomIO: %s"%str) 
     # logging to be implemented here 

customio = CustomIO() 
subprocess.call(["python3", "print_process.py"], stdout=customio) 

しかし、私はこのコードを実行するとき、私は、このエラーメッセージが出ます:

Traceback (most recent call last):         
    File "call_test.py", line 9, in <module>       
     subprocess.call(["python3", "print_process.py"], stdout=customio) 
    File "/usr/lib/python3.4/subprocess.py", line 537, in call   
     with Popen(*popenargs, **kwargs) as p:       
    File "/usr/lib/python3.4/subprocess.py", line 823, in __init__  
     errread, errwrite) = self._get_handles(stdin, stdout, stderr)  
    File "/usr/lib/python3.4/subprocess.py", line 1302, in _get_handles 
     c2pwrite = stdout.fileno()          
io.UnsupportedOperation: fileno 

これが可能であれば、誰でも手掛かりがありますか?

私は間違ったベースクラスを継承していますか?

適切なメソッドがオーバーロードされていませんか?

または、私は完全にレールから外れていて、まったく別のやり方でこれを行うべきですか?

+1

サブプロセスは、実際のosファイル記述子を持つ実際のファイルオブジェクトを期待しています。パイプを試してみてください – georgexsh

答えて

2

サブプロセスの出力を処理する場合は、stdout=subprocess.PIPEを渡す必要があります。ただし、call()run()は、プロセスが終了するまで待機してから、これらの機能を使用してリアルタイムで処理することはできません。

あなたはsubprocess.Popenを使用する必要があります。

import subprocess as sp 

def handle_output(output_line): 
    ... 

my_process = sp.Popen(["python3", "print_process.py"], 
         stdout=sp.PIPE, 
         universal_newlines=True) # changes stdout from bytes to text 

for line in my_process.stdout: 
    handle_output(line) 

my_process.wait() 

更新:あなたの子プロセスで、出力バッファをフラッシュすることを確認してください:

while True: 
    print("Things", flush=True) 
    time.sleep(1) 
+0

これはリアルタイムでも出力を処理しないようですか?私はこれを実行すると、サブプロセスが何かを印刷する前に完了するのを待ちます。 – Bobbzorzen

+0

私の謝罪です。何らかの理由で '[" yes "]'でテストしたときにうまくいきました。更新を参照してください。 – Phydeaux

+0

いいえ、これを行うには、子プロセスでフラッシュを追加しないでください。私の実際のケースでは、Pythonスクリプトではなく、代わりに制御できないプログラムです。 – Bobbzorzen

1

あなたはファイルとストリームを指定してオープンする必要がありますディスクリプタ。

Frequently Used Arguments

stdinstdoutstderrそれぞれ、実行されるプログラムの標準 入力、標準出力と標準エラーファイルハンドルを指定します。これはちょうど、インメモリストリームであるため、filenoio.IOBaseのために実装されていません。 有効な値は、PIPE,DEVNULL、既存のファイル記述子( の正の整数)、既存のファイルオブジェクト、およびNoneです。 PIPEは、子への新しいパイプを作成することを示す を示します。 DEVNULLは、 という特殊ファイルos.devnullが使用されることを示します。 Noneのデフォルト設定では、リダイレクトは行われません。

したがって、ソケット、パイプ、およびオープンファイルをstdoutとして使用すると、ファイル記述子がstdoutとして子プロセスに渡されます。私はsubprocess.Popenのソケットを使用しませんでしたが、動作させることを期待しています。ここで重要なのは、ファイルディスクリプタが指すオブジェクトのタイプではなく、ファイルディスクリプタです。

関連する問題