Python - 如何调用系统命令或外部程序

我经常会碰到拿别人的代码过来用却发现不是 Python 写的代码的情况。这个时候,如果你想调用他的代码,要么自己费力地把他的和自己的代码翻译成同一种语言,要么利用语言特性直接调用(如 Lua 直接调用 C 函数),但其实最简便的办法是通过外部程序调用的方式调用他的程序,只要传入相关参数即可~本文就讲一下在 Python 下调用外部函数或者命令的几种方法~

os.system

这个函数和 C 语言中的 system() 函数是类似的。这个函数比较简单,但是只能调用系统命令,无法直接调用外部函数,也无法获取运行的返回值或者输出流什么的,简便但不够灵活。

os.spawn*

Python 中 os 模块自带的函数 spawn* 是我最早接触到可以调用外部程序的函数,根据 * 的不同具体一共有八个函数

1
2
3
4
5
6
7
8
os.spawnl(mode, path, args*)
os.spawnle(mode, path, args*, env)
os.spawnlp(mode, file, args*)
os.spawnlpe(mode, file, args*, env)
os.spawnv(mode, path, args)
os.spawnve(mode, path, args, env)
os.spawnvp(mode, file, args)
os.spawnvpe(mode, file, args, env)

不同字母代表的含义其实通过函数定义即可看出,具体分别是:

  • lv 的区别在于调用的参数是直接传入的还是通过列表对象进行传入的,从函数定义即可看出。
  • p 代表外部程序的文件本体将从系统 PATH 中进行寻找,只需输入文件名即可
  • e 代表所调用的程序的环境变量可以通过 env 参数来指定

mode 代表调用函数的线程模式,有如下几种:

  • os.P_NOWAIT: 调用外部程序后函数本身不会等待,将会立即返回,代码继续执行
  • os.P_WAIT: 调用外部程序后函数等待程序执行结束才会返回继续
  • os.P_DETACH: 与 os.P_NOWAIT 相似,但是新的线程会脱离所调用的控制台(也就是说新的程序将不会通过当前的控制台来输出)
  • os.P_OVERLAY: 当前线程将会被替换成新的线程,这意味着 spawn* 函数将一直不返回

subprocess

subprocess 模块据 Python 官方文档所说,是用来替代以下这些函数的:

  • os.system
  • os.spawn*
  • os.popen*
  • popen2.*
  • commands.*

subprocess 常用的函数或对象有这么几个:call, check_*, Popen。下面介绍一下它们的用法。

  • call: 调用程序,等待到程序执行完成后返回程序的返回值
  • check_call: 调用程序,等待到程序执行完成后,若返回值为 0 则函数返回,若返回值不为 0 则抛出 CalledProcessError 异常
  • check_output: 调用程序,将程序的输出字符串以 bytes 形式返回
  • Popen: 参数与 call 相同,新建 Popen 对象即会调用程序,并且将新线程的相关操作封装在了 Popen 对象内,包括检查状态,等待等等。

这些函数或类对象的调用方法与在 Shell 中直接调用十分相似,并且除了指定参数之外还可以通过 stdin, stdout, stderr 等参数来指定新进程的输入输出,还可以通过指定 shell 参数来让,命令通过 Shell 进行调用,以利用 Shell 的一些功能。

参考资料: