提问人:zuberuber 提问时间:11/11/2012 最后编辑:martineauzuberuber 更新时间:5/12/2023 访问量:370254
如何将“subprocess”命令与管道一起使用
How to use `subprocess` command with pipes
问:
我想与 一起使用。
我尝试了各种解决方案,但到目前为止没有任何效果。有人可以指导我怎么做吗?subprocess.check_output()
ps -A | grep 'process_name'
答:
610赞
Taymon
11/11/2012
#1
要在模块中使用管道,必须传递 .subprocess
shell=True
但是,由于各种原因,这并不可取,尤其是安全性。相反,请单独创建 and 进程,并将输出从一个进程传递到另一个进程,如下所示:ps
grep
ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait()
但是,在您的特定情况下,简单的解决方案是调用,然后调用输出。subprocess.check_output(('ps', '-A'))
str.find
评论
137赞
Nicolas
11/12/2012
+1 用于分离输出/输入以避免使用shell=True
10赞
Serge
1/27/2015
别忘了,错误只是意味着 grep 没有发现任何内容,所以这是正常行为。subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1
6赞
Papouche Guinslyzinho
8/25/2015
当我们已经有输出时,为什么我们需要 for。 等待子项终止,但子项的内容似乎已放入变量中ps.wait()
ps.wait.__doc__
output
3赞
Taymon
10/17/2015
@MakisH 您正在查看 ,它已被弃用,取而代之的是(即对象上的方法)。string.find
str.find
find
str
8赞
jfs
3/23/2016
注意:如果过早死亡; 如果它产生足够的输出来填充其 OS 管道缓冲区,则可能会无限期挂起(因为您尚未调用父级)。交换起始顺序,以避免它grep
ps
ps.stdout.close()
85赞
jkalivas
11/12/2012
#2
或者,您始终可以在子流程对象上使用 communicate 方法。
cmd = "ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)
communicate 方法返回标准输出和标准错误的元组。
评论
10赞
Paolo
3/13/2016
我认为使用比.有这样的警告:“当使用 stdout=PIPE 和/或 stderr=PIPE 时,这将死锁,并且子进程会为管道生成足够的输出,以便它阻止等待操作系统管道缓冲区接受更多数据。使用 communicate() 来避免这种情况。communicate
wait
6赞
EnemyBagJones
12/3/2016
为了澄清 Paolo 上面的评论,警告是等待,而不是沟通——也就是说,这就是他说沟通更好的原因。
0赞
Miguel Ortiz
8/18/2020
python3 中 ps.communicate()[0] 的输出返回一个 bytes 对象。
0赞
tripleee
7/11/2021
你正在重塑,不是太差,而是没有吸引力。正如文档所建议的,当库已经提供了更高级别的函数时,您应该避免使用低级函数,这些函数在一行代码中处理所有这些管道,通常具有更好的边界条件行为。subprocess.check_output
Popen
0赞
tripleee
7/11/2021
为什么要将标准误差重定向到 ?STDOUT
4赞
amoffat
11/12/2012
#3
您可以在 sh.py 中试用管道功能:
import sh
print sh.grep(sh.ps("-ax"), "process_name")
评论
3赞
tripleee
7/11/2021
链接已失效。
0赞
cyraxjoe
3/24/2022
不再了,链接已更新。
3赞
Shooe
11/13/2012
#4
另外,尝试使用命令而不是'pgrep'
'ps -A | grep 'process_name'
评论
2赞
Shooe
11/13/2012
如果你想要获取进程 ID,显然
31赞
AlcubierreDrive
6/16/2013
#5
请参阅有关使用子进程设置管道的文档:http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline
我还没有测试过以下代码示例,但它应该大致是您想要的:
query = "process_name"
ps_process = Popen(["ps", "-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close() # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0]
评论
2赞
Alvin
12/3/2013
检查失败后,请参阅 Taymon 下面的答案,了解在不乱七八糟的情况下工作的方法
2赞
RightmireM
5/29/2014
subprocess.check_output在 Python 2.6.9 中似乎不存在
2赞
Brent
8/14/2020
#6
command = "ps -A | grep 'process_name'"
output = subprocess.check_output(["bash", "-c", command])
评论
3赞
Charles Duffy
9/4/2020
为什么不使用并让它预置呢?此代码中的任何内容都不需要 bash。(也就是说,完全避免使用 shell 是更好的做法;这个用例是一个合理的用例,但是一旦参数开始参数化——比如将process_name作为参数——安全问题就会出现)。shell=True
['sh', '-c']
0赞
Brent
9/4/2020
它很有用,因为你不必拆分字符串,当你引用空格时,这会变得复杂。
1赞
Charles Duffy
9/4/2020
哼? 不需要拆分字符串。 将任何字符串转换为仅包含该字符串的列表 -- 因此,-- 因此,您将被附加到该列表之前,因此您最终会得到 ,正是您的代码在这里所做的,除了 / 差异。subprocess.check_output(command, shell=True)
Popen
[command]
shell=True
['sh', '-c']
['sh', '-c', command]
sh
bash
1赞
Charles Duffy
9/4/2020
...就此而言,如果您确实尝试将字符串拆分为一个列表并使用 ,则只有该列表的第一个元素将被视为代码;你会得到类似的东西.这不是一件有用的事情:当以这种方式调用时,shell 会以 being 、being 等方式运行......但是由于该命令不查看 、 等,因此所有额外的内容都被简单地忽略了。shell=True
['sh', '-c', 'ps', '-A', '|', 'grep', 'process_name']
ps
$0
-A
$1
|
ps
$0
$1
2赞
Charles Duffy
9/4/2020
如果你阅读 Lib/subprocess.py
,你会发现 和 之间没有区别。代码清晰而简单——这不是一个可能隐藏在细节中的魔鬼的地方。subprocess.check_output(["sh", "-c", command])
subprocess.check_output(command, shell=True)
43赞
anaken78
11/12/2020
#7
使用 from subprocess.run,您可以将一个命令的输出传递到第二个命令中。input
import subprocess
ps = subprocess.run(['ps', '-A'], check=True, capture_output=True)
processNames = subprocess.run(['grep', 'process_name'],
input=ps.stdout, capture_output=True)
print(processNames.stdout.decode('utf-8').strip())
评论
6赞
MightyInSpirit
1/26/2021
注意:仅适用于 Python 3.7.9 及更高版本。capture_output
2赞
CervEd
5/6/2021
做什么,目的是什么?check
capture_output
7赞
tripleee
7/11/2021
@CervEd 这两者都有明确的记录。 是选项组合的简写,如果子进程未返回成功(零)状态,则会引发错误。capture_output
stdout=supprocess.PIPE, stderr=subprocess.PIPE
check=True
2赞
CervEd
7/11/2021
@tripleee它们被记录在案,在笨拙的 Python 文档中的某个地方,但答案中没有关于为什么包含它们的细节。 例如,不是绝对必要的,但是为了答案起作用。使用这些选项的原因应作为答案的一部分check=True
capture_output=True
3赞
Eldritch Cheese
8/25/2021
这种方法的缺点是会将进程的所有标准输出读取到内存中。对于像 ps 这样的小程序,这可能没问题,但对于较大的分析管道,应该避免这样做。capture_output
0赞
Raúl Salinas-Monteagudo
5/12/2023
#8
我认为仅仅为了享受流水线而启动一个 shell 并不像它应该的那样优雅。
以下代码使用本机管道支持,它确实有效。subprocess
您可以轻松地对其进行修改,以将两个以上的进程添加到管道中。
#!/usr/bin/env python3
import subprocess
def ps_grep(pattern):
# First command-line
ps_command = ["ps", "-A"]
# Second command-line
grep_command = ["grep", pattern]
# Launch first process
ps_process = subprocess.Popen(ps_command, stdout=subprocess.PIPE)
# Launch second process and connect it to the first one
grep_process = subprocess.Popen(
grep_command, stdin=ps_process.stdout, stdout=subprocess.PIPE
)
# Let stream flow between them
output, _ = grep_process.communicate()
return output.decode()
if __name__ == "__main__":
print(ps_grep("python"))
评论
有 psutil
允许以可移植的方式获取进程信息。