私はcmd = subprocess.Popenを使用してコマンドを実行し、次にsubprocess.communicateを実行する方法を知っています。ほとんどの場合、Popenの 'argv'引数としてshlex.splitでトークン化された文字列を使用します。 「ls -l」の例:
import subprocess
import shlex
print subprocess.Popen(shlex.split(r'ls -l'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0]
ただし、パイプは機能していないようです...たとえば、次の例では、注記が返されます。
import subprocess
import shlex
print subprocess.Popen(shlex.split(r'ls -l | sed "s/a/b/g"'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0]
私が間違っていることを教えていただけますか?
THX
ここで、2つの別々のPopenオブジェクトをインスタンス化したいと思います。1つは「ls」用で、もう1つは「sed」用です。最初のPopenオブジェクトのstdout
属性をstdin
引数として2番目のPopenオブジェクトに渡します。
例:
p1 = subprocess.Popen('ls ...', stdout=subprocess.PIPE)
p2 = subprocess.Popen('sed ...', stdin=p1.stdout, stdout=subprocess.PIPE)
print p2.communicate()
さらにコマンドがある場合は、この方法でチェーンを続けることができます。
p3 = subprocess.Popen('prog', stdin=p2.stdout, ...)
サブプロセスの操作方法の詳細については、 サブプロセスのドキュメント を参照してください。
私はパイピングを助けるための小さな関数を作りました、それが役に立てば幸いです。必要に応じてPopensをチェーンします。
from subprocess import Popen, PIPE
import shlex
def run(cmd):
"""Runs the given command locally and returns the output, err and exit_code."""
if "|" in cmd:
cmd_parts = cmd.split('|')
else:
cmd_parts = []
cmd_parts.append(cmd)
i = 0
p = {}
for cmd_part in cmd_parts:
cmd_part = cmd_part.strip()
if i == 0:
p[i]=Popen(shlex.split(cmd_part),stdin=None, stdout=PIPE, stderr=PIPE)
else:
p[i]=Popen(shlex.split(cmd_part),stdin=p[i-1].stdout, stdout=PIPE, stderr=PIPE)
i = i +1
(output, err) = p[i-1].communicate()
exit_code = p[0].wait()
return str(output), str(err), exit_code
output, err, exit_code = run("ls -lha /var/log | grep syslog | grep gz")
if exit_code != 0:
print "Output:"
print output
print "Error:"
print err
# Handle error here
else:
# Be happy :D
print output
shlex
は、シェルルールに従ってスペースを分割するだけですが、パイプは扱いません。
ただし、次のように機能するはずです。
_import subprocess
import shlex
sp_ls = subprocess.Popen(shlex.split(r'ls -l'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
sp_sed = subprocess.Popen(shlex.split(r'sed "s/a/b/g"'), stdin = sp_ls.stdout, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
sp_ls.stdin.close() # makes it similiar to /dev/null
output = sp_ls.communicate()[0] # which makes you ignore any errors.
print output
_
help(subprocess)
による
_Replacing Shell pipe line
-------------------------
output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
_
HTH
"""
Why don't you use Shell
"""
def output_Shell(line):
try:
Shell_command = Popen(line, stdout=PIPE, stderr=PIPE, Shell=True)
except OSError:
return None
except ValueError:
return None
(output, err) = Shell_command.communicate()
Shell_command.wait()
if Shell_command.returncode != 0:
print "Shell command failed to execute"
return None
return str(output)