「外部コマンドを起動する」の編集履歴(バックアップ)一覧はこちら
外部コマンドを起動する - (2008/04/08 (火) 17:37:45) の最新版との変更点
追加された行は緑色になります。
削除された行は赤色になります。
前提条件
-今後os.popen2はsubprocessに置き換えられていくようなので、なるべくsubprocessを使う。
-linux,OSX,windows全部で使える手段が望ましい。
やりたいこと。
レンダラの起動です、当然ながら。
+ 別プロセスで起動。以下の理由のため、終了を待たない。
+ 標準出力結果を毎行リアルタイムにきちんとチェックする。エラーによっては強制終了。問題なければログに出す。
+ 標準出力、標準エラー両方まとめてしまう。
+ windowsのエラー報告ダイアログは抑止。さもないとVNCでイチイチつないで閉じるまで操作不能になってしまうし。
#code(){{
outptr = file(logFile, "a")
try:
#エラー報告ダイアログ抑止用
if sys.platform.startswith("win"):
import ctypes
SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX);
subprocess_flags = CREATE_NO_WINDOW
else:
subprocess_flags = 0
currentSubprocess = subprocess.Popen(command,shell=False,
stdout=subprocess.PIPE,
sstderr=subprocess.STDOUT,
creationflags=subprocess_flags)
print 'started process pid ['+str(currentSubprocess.pid)+']'
child_stdout= currentSubprocess.stdout
for line in child_stdout:
#errorチェックはここでする。
outptr.write(line)
except Exception,e:
print 'Error! currentSubprocess['+str(currentSubprocess.pid)+']'# it will be 1
print repr('Error...')
return 0
}}
思った通りには動いてる。
注意点として、batの場合、中で他の外部コマンドを起動するときはcallで読んでもらわないと外部エラー出力が流れてこない。
[[参考>http://www.oreillynet.com/onlamp/blog/2007/08/pymotw_subprocess_1.html]]
[[subprocessにおけるエラー報告ダイアログ抑止の参考>http://blogs.activestate.com/ericp/2007/11/supressing-the.html]]
自分の状況では、この例がもっともフィットしました。
[[試験運用中なLinux備忘録>http://d.hatena.ne.jp/kakurasan/20080413/p1]]
[[O'REILLY>http://www.oreillynet.com/onlamp/blog/2007/08/pymotw_subprocess_1.html]]
[[subprocessにおけるエラー報告ダイアログ抑止の参考>http://blogs.activestate.com/ericp/2007/11/supressing-the.html]]
----
py2exe内で外部プロセスを使うプログラムA.exeを作成、
プログラムBからプログラムAを外部プロセスとして呼ぶ場合、
一定量まで標準出力を呼んでからまとめて出す、ようなおかしな状況に。
readlineのバッファ量の設定と思ったのだが
[[Python Matrix Jp>http://python.matrix.jp/tips/compatibility/subprocess.html]]
プログラムA内でsys.stdout.flush()やsys.stdout.close()をよぶ、といった解決法がありそう。
[[subprocess -popen - reading stdout from child - hangs>http://bytes.com/forum/thread712353.html]]
[[西尾泰和のはてなダイアリー(Pythonで子プロセスの出力を読む)>http://d.hatena.ne.jp/nishiohirokazu/20080407/1207536676]]
[[西尾泰和のはてなダイアリー(子プロセスに標準入力と標準出力を中継)>http://d.hatena.ne.jp/nishiohirokazu/20080404/1207312557]]
*子プロセス以下をすべてkillしたい
subprocess.Popenに
preexec_fn= os.setsid
とオプション指定すると、サブプロセスがプロセスグループ(Process Group)のトップになるため
os.killpg(pgid, signal.SIGTERM)
したときに、親プロセスを巻き込まずにkillすることができます。
プロセス情報を操作するのはosモジュールの方にあります。
[[プロセスのパラメタ>http://www.python.jp/doc/release/lib/os-procinfo.html]]
Pythonではありませんが、Unixのプロセスについて分かりやすく説明されてます。
[[プロセス制御>http://www.adl.nii.ac.jp/~moro/unix-programmer/faq-j_2.html#SEC26]]
*spaceのあるパスでうまくいかない
#highlight(python){{
path = 'C:/Documents and Settings/user'
cmd = ['C:/Program Files/TortoiseSVN/bin/SubWCRev.exe', path]
p = subprocess.Popen(
cmd,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
}}
このpathの方にスペースがあると、コマンド自体、C:/Programまでと判断されてしまう?
解決法は、shell=Falseです。