2017-12-27 24 views
0

I持って、元のスクリプトから別のPythonスクリプトを実行するPythonスクリプトに次の行:subprocess.Popenは()がコンソールに出力通信しますが、ファイルログに記録しない

subprocess.Popen("'/MyExternalPythonScript.py' " + theArgumentToPassToPythonScript, shell=True).communicate() 

上記の行を使用して別のPythonファイルにあるprint()のステートメントは、メインのPythonスクリプトのコンソールに表示されます。

ただし、これらのステートメントは、がスクリプトが書き込むログに反映されていないです。

誰もがこれを修正する方法を知っているので、.txtファイルはメインのPythonスクリプトの実際のコンソールテキストを正確に反映していますか?


これは私がリアルタイムで、.txtファイルとしてコンソールを保存するために使用していますthe methodです:私は必ずしもこの方法に装着されていないのです

import sys 
class Logger(object): 
    def __init__(self): 
     self.terminal = sys.stdout 
     self.log = open("/ScriptLog.txt", "w", 0) 
    def write(self, message): 
     self.terminal.write(message) 
     self.log.write(message) 


sys.stdout = Logger() 

。私は詳細を達成する方法に興味を持っています。

+0

あなたは、すべての書き込みの後に 'self.log.flush()'することができます。基本的に、Pythonは、バッファに十分なデータがあるか、ファイルハンドルが閉じられる(たとえば、アプリケーションが停止したとき)まで、ファイルへの書き込みを待機します。 –

+0

'self.log.write(message)'の後に 'self.log.flush()'を挿入しようとしました。これを行っても何も変わりませんでした。 .txtファイルにはまだ外部スクリプトの 'print'テキストは含まれていません。 – Crickets

+0

お待ちください、このスクリプトはかなり危険です。さらに、あなたのプログラムは引数を全く印刷しません。だから私はこれが引数を出力するのはシェルそのものだと思います。 –

答えて

0

subprocessは新しいプロセスを生成し、実際には親プロセスとは通信しません(ほとんど独立したエンティティです)。その名前にもかかわらず、communicateメソッドは、親プロセスから子プロセスにデータを送受信する方法です(ユーザーが端末上に何かを入力したことをシミュレートするなど)。

サブプロセスは数値(ファイル識別子またはファイル番号)を使用します。サブプロセスがプロセスを生成するとき、子プロセスは、標準出力がO.で識別されたファイルであることだけを知る。 7(数字のように)ですが、それはかなりです。サブプロセスは、独立して、「Hey!ファイル番号7は何ですか?私に教えてください、私はそれに書き込むものがあります。(C forkが何をするのか理解することが、ここでは非常に便利です)

基本的には、生成されたサブプロセスはあなたLoggerクラスを理解していません。これは、ファイル内にファイルを書き込む必要があることを知っているだけです。OS内で一意に識別され、番号が付いているファイルで、特に指定しない限り、その番号は標準出力のファイル記述子に対応します(ただし、下記の2つは、あなたが望むならそれを変更することができます)

あなたはいくつかの "解決策"を持っています...ファイルへ

  1. クローン(tee)標準出力に、何かがstdoutに書き込まれたときので、手術システムはまた、あなたのファイルに書き込みます(これは本当にPythonの関連はない...それはOSの関連です):

    import os 
    import tempfile 
    import subprocess 
    
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    p = subprocess.Popen("python ./run_something.py | tee %s" % file_log, shell=True) 
    p.wait() 
    
  2. それぞれのfileno()機能を使用してファイルに、端末ORに書き込みするかどうかを選択します。 (私はsys.stdoutを上書き快適に感じることはありません)

    import os 
    import tempfile 
    import subprocess 
    
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    with open(file_log, 'w') as f: 
        p = subprocess.Popen("python ./run_something.py", shell=True, stdout=f.fileno()) 
        p.wait() 
    
  3. すると、私は個人的に「より安全」を見つける何を:たとえば、ファイルへのみを書くことだけでコマンドを実行させて、変数にその出力を保存しますそして、(親プロセスで)後でそれを拾う:

    import os 
    import tempfile 
    import subprocess 
    
    p = subprocess.Popen("python ./run_something.py", shell=True, stdout=subprocess.PIPE) 
    p.wait() 
    contents = p.stdout.read() 
    # Whatever the output of Subprocess was is now stored in 'contents' 
    # Let's write it to file: 
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    with open(file_log, 'w') as f: 
        f.write(contents) 
    

    この方法で、あなたはまた、サブプロセスが端末に「言った」ものは何でも出力にあなたのコードのどこかprint(contents)を行うことができます。例示の目的のために

、スクリプト "./run_something.pyは" ちょうどこのです:

print("Foo1") 
print("Foo2") 
print("Foo3") 
+0

私は解決#3で終わった。それは素晴らしい作品です。私は単純に '' print(contents) 'を行うことができ、.txtログは' contents'を反映します。私は詳細な答えを感謝します。 – Crickets

+0

確かに...そして、私にとって、_processes_(スレッドは何か違う)は、基本的にはファイル間でしか通信できないことを理解することが非常に重要でした。それは、2つの完全に別々の「もの」が共通のファイルを使用して「話す」(待ち行列と呼ぶ、それをバッファと呼ぶ...同じ考え方):プロセス1がファイルに書き込み、プロセス2がそこから読み込みを行い、他の多くのバリエーションがありますが、ファイルはプロセスを一緒に「リンク」できる唯一のものです – BorrajaX

1

本当にsubprocess.Popenさんのcommunicate()メソッドが必要ですか?あなたは出力がほしいと思うようです。それはsubprocess.check_output()のためです。

これを使用すると、組み込みのloggingモジュールを使用して、複数の出力先への出力ストリームを「tee」することができます。

import logging 
import subprocess 
import sys 

EXTERNAL_SCRIPT_PATH = '/path/to/talker.py' 
LOG_FILE_PATH = '/path/to/debug.log' 

logger = logging.getLogger('') 
logger.setLevel(logging.INFO) 

# Log to screen 
console_logger = logging.StreamHandler(sys.stdout) 
logger.addHandler(console_logger) 

# Log to file 
file_logger = logging.FileHandler(LOG_FILE_PATH) 
logger.addHandler(file_logger) 

# Driver script output 
logger.info('Calling external script') 

# External script output 
logger.info(
    subprocess.check_output(EXTERNAL_SCRIPT_PATH, shell=True) 
) 

# More driver script output 
logger.info('Finished calling external script') 

常に、shell=Trueに注意してください。電話をsubprocess.check_output(['/path/to/script.py', 'arg1', 'arg2'])と書くことができるのであれば、そうしてください!

関連する問題