深入理解python中的subprocess模块
原创深入领会Python中的subprocess模块
在Python编程中,经常性需要执行系统命令或者运行其他程序。Python标准库中的subprocess模块正是用来处理这些任务的。它提供了一个高级接口来创建和操作进程,从而替代了os.system、os.spawn*、os.popen*、popen2.*、commands.*等旧模块。
subprocess模块的关键功能
subprocess模块提供了多种方法来创建子进程,以下是几个关键的方法:
- subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
- subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None)
使用subprocess.run执行命令
subprocess.run是Python 3.5及以上版本提供的一个便捷方法,用于执行命令并等待命令执行完成。
import subprocess
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print('Have {} bytes in stdout:{}'.format(len(result.stdout), result.stdout.decode()))
print('Have {} bytes in stderr:{}'.format(len(result.stderr), result.stderr.decode()))
创建子进程:subprocess.Popen
当你需要更细粒度的控制时,可以使用subprocess.Popen类来创建子进程。它允许你读取子进程的输出,写入子进程的输入,或者与子进程进行更错综的交互。
import subprocess
# 创建一个子进程
process = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# 获取标准输出和差错输出
stdout, stderr = process.communicate()
print('STDOUT:', stdout)
print('STDERR:', stderr)
处理shell=True
当你将shell参数设置为True时,你可以执行一个shell命令字符串,而不是一个命令列表。
import subprocess
result = subprocess.run('echo "Hello from subprocess"', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)
差错处理
你可以通过检查subprocess.run()的返回值或者subprocess.Popen的returncode属性来检测命令是否顺利执行。
import subprocess
try:
result = subprocess.run(['false'], check=True)
except subprocess.CalledProcessError as e:
print(f'Command failed with returncode {e.returncode}')
保险考虑
当使用subprocess模块时,保险是一个重要的考虑因素。以下是一些最佳实践:
- 避免使用shell=True,除非确实需要。
- 当需要传递用户输入到子进程时,应始终使用args列表形式,而不是shell=True。
- 当使用shell=True时,确保传递的命令不包含用户控制的部分。
总结
subprocess模块是一个有力的工具,可以用于与系统命令和子进程交互。领会怎样正确使用它,可以帮助你编写出更高效、保险的代码。