在Python中如何调用外部命令

0 投票
最新提问 1月 14, 2017 用户: yass (220 分)

如何从Python脚本中调用外部命令,就像在Unix shell或Windows命令提示符下一样?

2 个回答

0 投票
最新回答 1月 14, 2017 用户: LX5818 (390 分)

有两种方法:

一是os.system:

import os
os.system("ls -a")

请注意,这是种方法有风险,因为输入的命令无法保证安全性。

二是subprocess:

from subprocess import call
call(["ls", "-l"])

subprocess与os的区别是前者更灵活(你可以得到stdout、stderr、“真正”的状态码,更好的错误处理等等)。我觉得os.system已经过时,建议使用subprocess。

如果是写一次性的脚本,用os.system就足够了。

0 投票
最新回答 1月 14, 2017 用户: grace (370 分)

os.system不错,但有点过时。它也不是很安全。最好使用subprocess,subprocess不直接调用sh和因此比os.system更安全。了解更多信息在这里

下面是调用外部程序的方法及其优点和缺点的总结:

  1. os.system("some_command with args")将命令和参数传递到系统的shell。这种方法很好用,因为你可以以这种方式运行多个命令,并设置管道和输入/输出重定向。例如:

    os.system("some_command < input_file | another_command > output_file")  
    

    然而,虽然这很方便,但你必须手动处理shell字符的转义,如空格等。另一方面,这也允许你运行命令,仅仅是shell命令,而不是实际的外部程序。见文档

  2. stream = os.popen("some_command with args")会做同样的事情,os.system不同的是它给你一个类文件对象,你可以用它来访问标准的输入/输出这一进程。还有3个其他的popen函数,所有处理的i/o略有不同。如果你把所有的东西作为一个字符串,那么你的命令被传递给shell;如果你将它们作为列表传递,那么你不需要担心转义任何字符。见文档

  3. 在Popen类的subprocess模块。这是为了替代os.popen,但其缺点是由于全面而变得稍微复杂一些。例如:

    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
    

    代替:

    print os.popen("echo Hello World").read()
    

    但是, 在一个统一的类中拥有所有的选项, 而不是四个不同的 popen 函数是很好的。见文档

  4. 来自子进程模块的调用函数。 这基本上就像Popen类和所有相同的参数,但它只是简单的等待,直到命令完成,并给你的返回代码。 例如:

    return_code = subprocess.call("echo Hello World", shell=True)  
    

    文档

  5. 如果你使用Python 3.5或更高版本,可以使用新的subprocess.run函数,功能类似,但更灵活,并在命令执行完毕后返回一个CompletedProcess对象。

  6. 在C语言中,os模块也有所有的fork/exec/spawn函数,但不建议直接使用它们。建议使用subprocess模块。

最后请注意,对于所有的方法,你传递的最终命令由shell作为字符串执行,你需要转义它。如果你传递的字符串的任何部分不能完全受信任,则会产生严重的安全隐患。例如,如果用户可以输入字符串的某些部分。如果不确定, 则只能使用常量。示例代码:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

并想象用户输入“hello world && rm -rf /”。

欢迎来到编程助手,编程方面有什么不懂的问题可以尽管在这里提问,你将会收到热心爱好者的回答。
...