使用os
模块中的更具体方法而不是使用os.system
或subprocess
模块执行命令,有四个充分的理由:
- 冗余 - 产生另一个进程是多余的,浪费时间和资源。
- 可移植性 -
os
模块中的许多方法适用于多个平台,而许多shell命令是特定于操作系统的。
- 理解结果 - 引发进程以执行任意命令会强制你从输出中解析结果并理解命令何时以及为什么出错。
- 安全性 - 进程可以潜在地执行它收到的任何命令。这是一个薄弱的设计,可以通过在
os
模块中使用特定方法来避免。
实际上,在您执行最终的系统调用(例如您的chmod
)之前,您正在执行一个多余的“中间人”。这个中间人是一个新进程或子shell。
来自os.system
:
在子shell中执行命令(字符串)...
subprocess
只是一个生成新进程的模块。
您可以在不生成这些进程的情况下完成所需的操作。
os
模块的目的是提供通用的操作系统服务,其描述以以下内容开头:
此模块提供了一种使用操作系统相关功能的可移植方式。
你可以在Windows和Unix上都使用
os.listdir
。尝试使用
os.system
/
subprocess
实现此功能将强制您维护两个调用(用于
ls
/
dir
)并检查您所在的操作系统。这不是很便携,并且稍后会引起更多的挫败感(请参见
处理输出)。
理解命令结果:
假设您想要列出目录中的文件。
如果您使用os.system(“ls”)
/subprocess.call(['ls'])
,则只能获取进程的输出,这基本上是一个带有文件名的大字符串。
如何从两个文件中区分出名称中带有空格的文件?
如果您没有权限列出文件怎么办?
应该如何将数据映射到Python对象?
这些只是我脑海中的一些问题,虽然有解决这些问题的方法,但为什么要再次解决已经为您解决的问题呢?
这是遵循不要重复自己原则的一个示例(通常称为“DRY”),通过不重复已经存在并且可以免费使用的实现来实现。
安全性:
os.system
和subprocess
非常强大。当你需要这种力量时,它是好的,但是当你不需要时,它是危险的。当你使用os.listdir
时,你知道它只能列出文件或引发错误。当你使用os.system
或subprocess
来实现相同的行为时,你可能最终会做一些你本不想做的事情。
注入安全性(见shell注入示例):
如果你将用户输入作为新命令使用,那么你基本上给了他一个Shell。这就像SQL注入为用户提供了数据库中的Shell。
一个示例是形如:
# ... read some user input
os.system(user_input + " some continutation")
这可以轻松地被利用来使用输入运行
任意代码:
NASTY COMMAND;#
,以创建最终结果:
os.system("NASTY COMMAND
有许多这样的命令可能会使您的系统处于风险之中。
print
,而不使用os.system("echo Hello world!")
? - user253751os.path
来处理路径,而不是手动处理它们:它可以在运行的每个操作系统上工作。 - Bakuriuos.chmod
不会调用 shell 执行chmod
程序。使用os.system('chmod ...')
会启动一个 shell 来解释一个字符串并调用另一个可执行文件来调用 C 的chmod
函数,而os.chmod(...)
直接调用 C 的chmod
。 - user2357112