在执行命令时,有四种很强的情况os
比起使用os.system
或subprocess
模块,更喜欢在模块中使用Python更具体的方法:
- 冗余 -产生另一个进程是多余的,浪费时间和资源。
- 可移植性 -
os
模块中的许多方法可在多个平台上使用,而许多shell命令是特定于OS的。
- 了解结果 -生成执行任意命令的进程会迫使您从输出中解析结果,并了解命令是否以及为什么做错了什么。
- 安全 -进程可以执行它给出的任何命令。这是一个较弱的设计,可以通过使用
os
模块中的特定方法来避免。
实际上,您在执行最终系统调用的过程chmod
中正在执行一个冗余的“中间人”(在您的示例中)。这个中间人是一个新的进程或子外壳。
来自os.system
:
在子shell中执行命令(字符串)...
并且subprocess
仅仅是产生新流程的模块。
您可以执行所需的操作而无需产生这些过程。
该os
模块的目的是提供通用的操作系统服务,其描述始于:
该模块提供了使用依赖于操作系统的功能的便携式方法。
您可以os.listdir
在Windows和Unix上使用。尝试将os.system
/ subprocess
用于此功能将迫使您维护两个调用(ls
/ dir
),并检查您所使用的操作系统。这不是便携式的,以后会引起更大的挫败感(请参阅处理输出)。
了解命令的结果:
假设您要列出目录中的文件。
如果使用os.system("ls")
/ subprocess.call(['ls'])
,则只能返回该进程的输出,这基本上是一个带有文件名的大字符串。
如何从两个文件中分辨出文件名中带有空格的文件?
如果您无权列出文件怎么办?
您应该如何将数据映射到python对象?
这些只是我的头上问题,尽管有解决这些问题的方法-为什么要再次解决为您解决的问题?
这是通过不重复已经存在且可供您免费使用的实现来遵循“ 不要重复自己”原理(通常称为“ DRY”)的示例。
安全:
os.system
并且subprocess
功能强大。当您需要这种功能时,这很好,但是当您不需要这种功能时,这是危险的。使用时os.listdir
,您知道它只能执行其他操作,然后列出文件或引发错误。当您使用os.system
或subprocess
实现相同的行为时,您可能最终会做一些原本不想做的事情。
注射安全性(请参见外壳注射示例):
如果将来自用户的输入用作新命令,则基本上已经给了他一个外壳。这就像SQL注入为用户在DB中提供外壳程序一样。
一个示例将是以下形式的命令:
# ... read some user input
os.system(user_input + " some continutation")
这可以很容易利用来运行任何使用输入任意代码:NASTY COMMAND;#
创建最终的:
os.system("NASTY COMMAND; # some continuation")
有许多这样的命令会使您的系统处于危险之中。