gpt4 book ai didi

python - 子进程相对于 os.system 的优势

转载 作者:太空狗 更新时间:2023-10-29 17:56:40 24 4
gpt4 key购买 nike

我最近看到一些关于堆栈溢出的帖子说 subprocess 比 os.system 好得多,但是我很难找到确切的优势。

我遇到的一些事情的例子:
https://docs.python.org/3/library/os.html#os.system

"The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function."



不知道它在哪些方面更强大,我知道它在很多方面更容易使用 subprocess 但它实际上在某些方面更强大吗?

另一个例子是:

https://stackoverflow.com/a/89243/3339122

The advantage of subprocess vs system is that it is more flexible (you can get the stdout, stderr, the "real" status code, better error handling, etc...).



这个帖子有 2600+ 票。再次找不到关于更好的错误处理或真实状态代码的含义的任何详细说明。

该帖子的最高评论是:

Can't see why you'd use os.system even for quick/dirty/one-time. subprocess seems so much better.



同样,我理解它使某些事情变得稍微容易一些,但我几乎不明白为什么,例如:
subprocess.call("netsh interface set interface \"Wi-Fi\" enable", shell=True)


os.system("netsh interface set interface \"Wi-Fi\" enabled")

谁能解释一些原因,它好多了?

最佳答案

首先,您正在削减中间人; subprocess.call默认情况下,避免生成检查您的命令的 shell,并直接生成请求的进程。这很重要,因为除了问题的效率方面之外,您对默认的 shell 行为没有太多控制权,而且它实际上通常在转义方面对您不利。
特别是不要做这个:

subprocess.call('netsh interface set interface "Wi-Fi" enable')
自从

If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.


相反,您将执行以下操作:
subprocess.call(["netsh", "interface", "set", "interface", "Wi-Fi", "enable"])
请注意,这里所有逃脱的噩梦都消失了。 subprocess处理转义(如果操作系统希望参数作为单个字符串 - 例如 Windows)或将分隔的参数直接传递给相关的系统调用(UNIX 上的 execvp)。
将此与必须自己处理转义进行比较,尤其是以跨平台方式( cmd 与 POSIX sh 的转义方式不同),尤其是中间的外壳弄乱了您的东西(相信我) ,您不想知道在调用 cmd /k 时为您的命令提供 100% 安全的转义是什么邪恶的困惑)。
另外,当使用 subprocess 时如果中间没有外壳,您肯定会得到正确的返回码。如果启动进程失败,你会得到一个 Python 异常,如果你得到一个返回码,它实际上是启动程序的返回码。与 os.system你无法知道你得到的返回码是来自启动的命令(如果 shell 设法启动它,这通常是默认行为)还是来自 shell 的一些错误(如果它没有设法启动它) )。

除了参数拆分/转义和返回代码之外,您还可以更好地控制启动的进程。即使与 subprocess.call (这是 subprocess 功能中最基本的实用功能)您可以重定向 stdin , stdoutstderr ,可能与启动的进程通信。 check_call类似,它避免了忽略失败退出代码的风险。 check_output涵盖了 check_call 的常见用例+ 将所有程序输出捕获到一个字符串变量中。
一旦你过去 call & friend (就像 os.system 一样阻塞),还有更强大的功能 - 特别是 Popen对象允许您异步处理启动的进程。你可以启动它,可能通过重定向的流与它交谈,检查它是否在做其他事情时不时运行,等待它完成,向它发送信号并杀死它——所有的东西都不仅仅是同步“通过 shell 使用默认的 stdin/stdout/stderr 启动进程并等待它完成”即 os.system提供。

所以,总结一下,用 subprocess :
  • 即使在最基本的级别(call 和 friend ),您:
  • 通过传递 Python 参数列表避免逃避问题;
  • 避免 shell 弄乱你的命令行;
  • 要么您有异常,要么是您启动的进程的真正退出代码;不会混淆程序/shell 退出代码;
  • 有可能捕获标准输出并通常重定向标准流;

  • 当您使用 Popen :
  • 您不限于同步接口(interface),但您实际上可以在子进程运行时做其他事情;
  • 您可以控制子进程(检查它是否正在运行,与其通信,杀死它)。


  • 鉴于 subprocess确实比 os.system可以 - 并且以更安全、更灵活(如果需要)的方式 - 没有理由使用 system反而。

    关于python - 子进程相对于 os.system 的优势,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44730935/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com