如何将一个子进程的输出传递给另一个子进程的输入?
How to pass the output of a subprocess to the input of another subprocess?
我有一些 bash 命令可以处理项目的 csv 文件,我正在尝试将它们转换为 Python 脚本。问题是我想将子进程的输出作为新子进程的输入传递,而不必创建额外的文件。下面的代码从 csv 文件中提取第 12 个字段,其中包含我要使用第二个命令处理的链接:
import sys
import getopt
import subprocess
import shlex
def main(argv):
inputfile=''
try:
opts,args=getopt.getopt(argv,"hi:",["ifile="])
except getopt.GetoptError:
print('The correct format is Script.py -i <result csv file>')
sys.exit(2)
for opt,arg in opts:
if opt == '-h':
print('Script.py -i <input csv file>')
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile=arg
print('Input file is ',inputfile)
def run_prog(prog):
p1 = subprocess.Popen(prog, shell=True, stdin=open(inputfile,'r'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p1.stdout.read())
second_command = 'for var in $(cat '+p1.stdout.read()+'); do echo ${var%/*}; done'
p2 = subprocess.Popen(shlex.split(second_command), stdin=p1.stdout, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p2.stdout.read())
def brokenlinks():
cmd=r"""awk -F "," '{print }'"""
run_prog(cmd)
brokenlinks()
if __name__ == "__main__":
main(sys.argv[1:])
我如何将 p1 的输出重定向到 p2 以便 运行 第二个命令?我现在得到的代码向我抛出“var is unexpected at this time”。打印时 p2.stdout.read().
您实际上在第二个命令期间获取了两次 p1.stdout
:首先是在命令本身期间(这是一个坏主意,因为它可能被利用来注入代码,以及其他问题),然后是在标准输入期间p2.
我建议取消第一次提取,只依赖于将 p1.stdout 的管道传递给 p2.stdin 的事实。
def run_prog(prog):
p1 = subprocess.Popen(prog, shell=True, stdin=open(inputfile,'r'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p1.stdout.read())
second_command = 'while read var; do echo ${var%/*}; done'
p2 = subprocess.Popen(shlex.split(second_command), stdin=p1.stdout, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p2.stdout.read())
这里唯一的区别是 second_command
的定义,它使用 while
读取每一行而不是使用 for
.
循环
有很多方法可以在不依赖 for
或 while
循环的情况下执行相同的操作。由于您需要删除最后一个斜线之后的字符,包括斜线本身,您可以使用 sed:
second_command = "sed 's,/[^/]*$,,'"
当然,您也可以在 Python 中执行所有这些操作,但我认为这不是您最初来这里的原因。
我有一些 bash 命令可以处理项目的 csv 文件,我正在尝试将它们转换为 Python 脚本。问题是我想将子进程的输出作为新子进程的输入传递,而不必创建额外的文件。下面的代码从 csv 文件中提取第 12 个字段,其中包含我要使用第二个命令处理的链接:
import sys
import getopt
import subprocess
import shlex
def main(argv):
inputfile=''
try:
opts,args=getopt.getopt(argv,"hi:",["ifile="])
except getopt.GetoptError:
print('The correct format is Script.py -i <result csv file>')
sys.exit(2)
for opt,arg in opts:
if opt == '-h':
print('Script.py -i <input csv file>')
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile=arg
print('Input file is ',inputfile)
def run_prog(prog):
p1 = subprocess.Popen(prog, shell=True, stdin=open(inputfile,'r'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p1.stdout.read())
second_command = 'for var in $(cat '+p1.stdout.read()+'); do echo ${var%/*}; done'
p2 = subprocess.Popen(shlex.split(second_command), stdin=p1.stdout, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p2.stdout.read())
def brokenlinks():
cmd=r"""awk -F "," '{print }'"""
run_prog(cmd)
brokenlinks()
if __name__ == "__main__":
main(sys.argv[1:])
我如何将 p1 的输出重定向到 p2 以便 运行 第二个命令?我现在得到的代码向我抛出“var is unexpected at this time”。打印时 p2.stdout.read().
您实际上在第二个命令期间获取了两次 p1.stdout
:首先是在命令本身期间(这是一个坏主意,因为它可能被利用来注入代码,以及其他问题),然后是在标准输入期间p2.
我建议取消第一次提取,只依赖于将 p1.stdout 的管道传递给 p2.stdin 的事实。
def run_prog(prog):
p1 = subprocess.Popen(prog, shell=True, stdin=open(inputfile,'r'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p1.stdout.read())
second_command = 'while read var; do echo ${var%/*}; done'
p2 = subprocess.Popen(shlex.split(second_command), stdin=p1.stdout, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(p2.stdout.read())
这里唯一的区别是 second_command
的定义,它使用 while
读取每一行而不是使用 for
.
有很多方法可以在不依赖 for
或 while
循环的情况下执行相同的操作。由于您需要删除最后一个斜线之后的字符,包括斜线本身,您可以使用 sed:
second_command = "sed 's,/[^/]*$,,'"
当然,您也可以在 Python 中执行所有这些操作,但我认为这不是您最初来这里的原因。