subprocess.Popen
、インスタンス化されると、プログラムを実行します。ただし、それを待つことはありません。cmd &
と入力したかのように、バックグラウンドで起動します。 シェルで。したがって、上記のコードでは、基本的に競合状態を定義しています。挿入が時間内に終了できる場合は正常に見えますが、そうでない場合は予期しない出力が得られます。最初のrun()
を待っていません PIDを終了するには、Popen
を返すだけです。 インスタンスと継続。
この動作がドキュメントとどのように矛盾するかはわかりません。Popenには、次のように、待機されていないことを示す非常に明確なメソッドがいくつかあるためです。
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
ただし、このモジュールのドキュメントが改善される可能性があることに同意します。
プログラムが終了するのを待つには、subprocess
を使用することをお勧めします の便利なメソッド、subprocess.call
、またはcommunicate
を使用する Popen
で オブジェクト(stdoutが必要な場合)。 2回目の通話ではすでにこれを行っています。
### START MAIN
# copy some rows from a source table to a destination table
# note that the destination table is empty when this script is run
cmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'
subprocess.call(cmd)
# check to see how many rows exist in the destination table
cmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
try: count = (int(process.communicate()[0][:-1]))
except: count = 0
さらに、ほとんどの場合、シェルでコマンドを実行する必要はありません。これはそのようなケースの1つですが、コマンドをシーケンスのように書き直す必要があります。そうすることで、従来のシェルインジェクションを回避し、次のように引用符を気にする必要がなくなります。
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
これも機能し、期待どおりに注入されません:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
インタラクティブに試してみてください。特にユーザー入力を受け入れる場合は、シェルインジェクションの可能性を回避します。シーケンスを機能させるのに問題が発生したため、サブプロセスと通信するためのあまり優れていない文字列メソッドを使用していると思われます:^)