python - 什么时候应该使用 system(3) 来运行外部进程?
问题描述
C 提供了使用shellsystem
运行子进程的标准函数,并且许多语言提供了类似的函数,例如AWK、Perl(带有单个参数)和PHP。有时这些功能被批评为不适合一般使用,无论是出于安全原因还是因为外壳不可移植或不是交互式使用的外壳。
其他一些语言似乎也同意:它们只提供了一种在没有 shell 的情况下运行进程的方法,例如Java(它标记任何单个字符串参数本身)和Tcl。Python 提供了直接的包装器和复杂的替代品,可以避免使用 shell 并明确推荐后者(就像用户社区一样)。
当然,对于许多应用程序来说,shell 是不必要的复杂性;运行外部进程可能会带来死锁、孤儿进程、不明确的退出状态和文件描述符共享等问题,并且在运行mkdir
或echo $VAR
. 但是,假设它的system
存在是有原因的,那么什么时候使用它是正确的工具?
解决方案
即使假设一个用例适合运行外部进程,特别是通过 shell 运行一个(不能像 with 一样过滤输出popen
),对于 C 和 Python(使用实际的C system(3)
),还有额外的警告。POSIX为 :指定了额外的行为system
:它在执行过程中忽略 SIGINT
和SIGQUIT
阻塞。SIGCHLD
基本原理是用户(可以从终端发送SIGINT
和发送)在执行期间与子进程交互,而不是父进程,并且必须在不受应用程序干扰的情况下为其子进程处理。SIGQUIT
system
SIGCHLD
这直接暗示了问题的答案:system
只有在
- 用户直接要求执行特定的 shell 命令(例如, with
!
inless
),并且 - 应用程序不需要对在此期间退出的任何其他子进程做出反应(例如,它不应该是多线程的)。
如果 #1 不满足,用户可能会发送一个终端信号,期望它终止整个进程并让它只杀死(如果不是不可见的话,意外的)子进程。Linux 手册页特别注意在用户无法中断的循环中使用它。可能会注意到一个孩子已经退出并重新启动它,但这是不可靠的,因为某些程序(例如Python)在接收到某些信号时而exit
不是重新启动它以指示它们退出的原因 - 并且因为 shell(由!)将退出状态与信号终止状态混为一谈。system
在 Python 中,错误处理问题因os.system
遵循 C 退出状态(读取:错误代码)约定而不是将失败报告为异常而导致用户忽略子项的退出状态这一事实更加复杂。
推荐阅读
- android - FirebaseAuth:getGoogleApiForMethod() 返回 Gms:com.google.firebase.auth.api.internal.zzal@9cd3393
- c# - Visual Studio 2017 使用 .net 标准库时复制太多文件
- javascript - 在 JavaScript 中调用函数时出错
- javascript - 在 app.js 中的 res.render 之后使用 return 被认为是一种好的做法?
- php - 使用 PHP 将 HTML 表单插入 MySQL
- python - 在 python/django 中的 html 画布上绘制形状
- java - 如何计算程序在 Eclipse 中“运行”的次数?
- python - 使用 Python 的 Simplex:如何设置代码
- light-4j - 关于 light-4j 应用程序缓存的任何建议?
- java - 在 JBoss 上启动 Spring webapp 问题