Is it good style to call bash commands within a Python script using os.system(“bash code”)?
我想知道在使用os.system()的Python脚本中调用bash命令是否被认为是一种好的风格。我还想知道这样做是否安全。
我知道如何在bash和python中实现我需要的一些功能,但是在bash中实现它要简单得多,而且更直观。但是,我觉得编写os.system("bash代码")非常黑客。
具体来说,我想将以某个扩展名结尾的所有文件移动到一个目录中。
在bash中:*mv.ext/path/to/destination在python(伪代码)中:对于目录中的文件:如果file.endswith("ext"):将文件移动到目标
在这种情况下,我应该怎么做?
首先,您的示例使用mv,它是coreutils中的程序,而不是bash。
使用os.system()调用外部程序被认为是糟糕的风格,因为:
- 您正在创建特定于平台的依赖项
- 您正在创建特定于版本的依赖项(是的,甚至coreutils有时也会更改!)
- 您需要检查是否存在外部命令(以及它们是否在$path中,以及是否可由用户执行等)。
- 必须使用返回代码对命令进行错误检查。在语言错误代码或异常中使用更好。(os.system()不允许分析stdout/stderr)
- 您必须自己处理用空格引用变量(或将其转义)。
- python已经通过提供库为您完成了这项工作!
像其他人已经提到的,查找glob,寻找shell-like模式匹配(globbing)和shutil。否则,您所需要的一切都已经在标准库中了。
1 2 3 4 5 | import glob import shutil for extfile in glob.glob('*.ext'): shutil.move(extfile,dest) |
此外,不应使用os.system()—而是查看子进程模块。
查看python的
使用Python函数来完成这类工作总是更好、更好的风格。对于Python来说,用独立于操作系统的方式编写脚本而不是使用bash并不难。
为什么要使用纯Python,
在这种情况下,我会用…
1 2 3 4 | import os for filename in os.listdir('.'): if filename.endswith('.ext'): os.rename(filename, os.path.join('path', 'to', 'new', 'destination', filename)) |
不过,也许还有更好的方法
仅引用问题就意味着最好使用纯Python解决方案。
这不是主意,因为它让你的脚本更不易移植。本机python脚本可以在安装了正确python库的任何UNIX或Windows计算机上运行。当您将shell命令添加到混合中时,您将打破这个限制,并突然被锁定到一个更窄的子集中。
有时您没有选择,但是如果是这样简单的事情,那么用Python编写本机代码会更有意义,而且启动速度更快(因为Python进程不必仅仅为了执行一个命令而生成一个新的shell)。
通常,python提供了"子进程"模块,允许您运行命令并对其输出进行广泛的控制。它允许您"生成新进程,连接到它们的输入/输出/错误管道,并获取它们的返回代码":
http://docs.python.org/library/subprocess.html