我想使用subprocess.check_output()
和ps -A | grep '进程名称'
一起使用。我尝试了各种解决方案,但目前为止没有什么效果。请问有人可以指导我如何做吗?
我想使用subprocess.check_output()
和ps -A | grep '进程名称'
一起使用。我尝试了各种解决方案,但目前为止没有什么效果。请问有人可以指导我如何做吗?
要使用管道来操作subprocess
模块,您必须传递shell=True
参数。
不过,出于各种原因,尤其是安全方面的考虑,这并不是个好主意。相反,应该分别创建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
。
shell=True
,此举值得赞扬。 - Nicolassubprocess.CalledProcessError: Command('('grep', 'process_name')')
表示 grep 没有找到任何内容,因此这是正常行为。请注意,不要改变原意。 - Sergeps.wait()
呢?ps.wait.__doc__
等待子进程终止,但子进程的内容似乎已经存储在 output
变量中了。 - Papouche Guinslyzinhostring.find
,现在应该使用str.find
(即str
对象上的方法find
)。 - Taymongrep
过早结束,而且ps
产生足够多的输出来填满其操作系统管道缓冲区(因为您没有在父进程中调用ps.stdout.close()
),则ps
可能会无限期地挂起。 交换起始顺序以避免此问题。 - jfs或者您始终可以在子进程对象上使用通信方法。
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方法返回标准输出和标准错误的元组。
communicate
比使用 wait
更好。文档中有这样的警告:"当使用 stdout=PIPE 和/或 stderr=PIPE 且子进程生成足够的输出以至于阻塞等待操作系统管道缓冲区接受更多数据时,这将导致死锁。使用 communicate() 可以避免这种情况。" - Paolosubprocess.check_output
,虽然不算太糟糕但也不够优雅。正如文档所建议的那样,当库已经提供了高级函数来处理所有这些繁琐的事情,并通过一行代码实现时,应避免使用底层的 Popen
,通常还能更好地处理边界条件。 - tripleee使用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())
capture_output
只适用于 Python 3.7.9 及以上版本。 - MightyInSpiritcheck
是用来做什么的?capture_output
的目的是什么? - CervEdcapture_output
是 stdout=subprocess.PIPE, stderr=subprocess.PIPE
选项组合的简写形式,而 check=True
则会在子进程未返回成功(零)状态时引发错误。 - tripleeecheck=True
并非必须的,但 capture_output=True
是回答能够正常工作的原因之一。应该将使用这些选项的原因作为回答的一部分包含进来。 - CervEdcapture_output
会将进程的所有标准输出读入内存。对于像ps这样的小程序,这可能没问题,但对于更大的分析管道,应该避免使用此方法。 - Eldritch Cheesequery = "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]
你可以在 sh.py 中尝试管道功能:
import sh
print sh.grep(sh.ps("-ax"), "process_name")
'pgrep'
命令而不是'ps -A | grep 'process_name'
。command = "ps -A | grep 'process_name'"
output = subprocess.check_output(["bash", "-c", command])
shell=True
并让它前置 ['sh', '-c']
呢?这段代码中没有任何需要 bash 的地方。(话虽如此,最好的做法是尽量避免使用 shell;这个用例是合理的,但一旦参数开始被参数化——比如将 process_name 作为参数传递——安全问题就会出现)。 - Charles Duffysubprocess.check_output(command, shell=True)
不需要你拆分字符串。Popen
将任何字符串转换为只包含该字符串的列表--因此,[command]
--所以使用shell=True
,您会得到['sh', '-c']
添加到该列表中,因此最终您会得到['sh', '-c', command]
,这正是您在此处的代码所做的,除了sh
/bash
之间的差异。 - Charles Duffyshell=True
,那么只有该列表的第一个元素会被视为代码;您会得到类似于['sh', '-c', 'ps', '-A', '|', 'grep', 'process_name']
的东西。这样做没有什么用:以这种方式调用时,shell会使用$0
作为-A
,$1
作为|
等运行ps
命令...但由于命令ps
不查看$0
,$1
等内容,所有额外的内容都会被忽略。 - Charles DuffyLib/subprocess.py
,你会发现 subprocess.check_output(["sh", "-c", command])
和 subprocess.check_output(command, shell=True)
之间 _实际上没有任何区别_。代码清晰简单 -- 这不是一个可能隐藏着魔鬼细节的地方。 - Charles Duffy我认为仅仅为了享受管道而启动一个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
的工具可以以便携的方式获取进程信息。 - jfs