如何在Linux上使用带管道的子进程模块?


在Python中,我们有**subprocess**模块,它允许我们使用额外的进程,并使开发人员的工作更加轻松。虽然还有其他模块提供与subprocess模块类似的功能,例如**os.spawn()、os.system()、os.popen()**等等,但推荐使用subprocess模块的原因是它比上面提到的所有其他类似模块都提供更高级别的接口。

为了能够将管道与subprocess模块一起使用,我们首先需要了解subprocess模块的功能。

示例

让我们考虑一个简单的subprocess模块示例,我将在其中打印外部命令,甚至不与它交互。

考虑以下示例:

创建一个名为sample.py的python文件,然后将以下代码放入该文件中:

import subprocess
subprocess.call(['ls -ltr', '-1'], shell=True)

使用以下命令运行sample.py文件:

python sample.py

输出

$ python sample.py

__init__.py
index.rst
interaction.py
repeater.py
signal_child.py
signal_parent.py
subprocess_check_call.py
subprocess_check_output.py
subprocess_check_output_error.py
subprocess_check_output_error_trap_output.py
subprocess_os_system.py
subprocess_pipes.py
subprocess_popen2.py
subprocess_popen3.py
subprocess_popen4.py
subprocess_popen_read.py
subprocess_popen_write.py
...

现在,当我们谈到使用subprocess模块时,我们最终会使用**Shell=True**标志,在许多情况下必须避免这种情况,而且也不推荐。

例如:

def count_number_of_lines(website):
return subprocess.check_output('curl %s | wc -l' % website, shell=True)

如果我在上面的示例中传递任何网站的URL,它将返回该URL上可用的行数。

例如,如果我传递‘www.google.com’,那么

输出

'7
'

但这绝对不推荐,因为它允许shell注入,如果您关心网站的安全,这将是一场噩梦。

更好的方法是使用管道,为此,我们可以将上面示例中的代码更改为如下所示:

def count_number_of_lines(website):
   args1 = ['curl', website]
   args2 = ['wc', '-l']
   process_curl = subprocess.Popen(args1, stdout=subprocess.PIPE,
                  shell=False)
   process_wc = subprocess.Popen(args2, stdin=process_curl.stdout,
                  stdout=subprocess.PIPE, shell=False)
   process_curl.stdout.close()
   return process_wc.communicate()[0]

输出

'7
'

更新于:2021年7月31日

362 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告