Windowsだとシステムからの文字コードはshift_jisなのでそれに対応
stderr = subprocess.PIPE
にすると、 proc.stdout.readline
を先に書いたとき、 stderr側での出力が貯まりすぎると、デッドロックが発生することがあるらしい。なので、stderrもSTDOUT側に流して、 stdout.readline
だけで1行ずつ読み込む。
import subprocess import sys def run(exe_path,current_dir=None,*, parse=None, silent_pre=False, silent_cout=False,end="\n"): if not silent_pre: print("Exe:",exe_path) if current_dir != None: print("Target:",current_dir) if current_dir != None: proc = subprocess.Popen(exe_path,cwd=current_dir, stdout = subprocess.PIPE, stderr = subprocess.STDOUT,shell=True) else: proc = subprocess.Popen(exe_path,stdout = subprocess.PIPE, stderr = subprocess.STDOUT,shell=True) for line in iter(proc.stdout.readline,b''): if silent_cout:continue try:line_str = line.rstrip().decode("utf8") except:line_str = line.rstrip().decode("shift_jis") if parse != None and parse(line_str) == False:continue print(line_str,end=end) proc.wait() ret = int(proc.returncode) if ret != 0: print("Return:",ret,"from",exe_path,"in",current_dir) return ret
完全に自信はない。これで良い?
communicate()
を使うと一気にstdoutもstderrも読めるらしいけど、リアルタイム表示したいので使えない。
簡略化したコード
def run(exe_path): proc = subprocess.Popen(exe_path,stdout = subprocess.PIPE, stderr = subprocess.STDOUT,shell=True) for line in iter(proc.stdout.readline,b''): try:line_str = line.rstrip().decode("utf8") except:line_str = line.rstrip().decode("shift_jis") print(line_str,end="\n") proc.wait() ret = int(proc.returncode) if ret != 0: print("Return:",ret,"from",exe_path) return ret
参照