欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

os与subprocess模块执行系统命令

程序员文章站 2022-03-25 16:24:55
https://docs.python.org/3/library/os.html https://docs.python.org/3/library/subprocess.html subprocess是对os.system的一个改进型模块,建议实际中使用subprocess模块内的命令来执行系统 ......

subprocess是对os.system的一个改进型模块,建议实际中使用subprocess模块内的命令来执行系统命令。关于他们之间的差别请详细阅读上述官方文档。

一、os.system与os.popen

1. os.system(command)

execute the command (a string) in a subshell. this is implemented by calling the standard c function system(), and has the same limitations。

on unix, the return value is the exit status of the process encoded in the format specified for 

on windows, the return value is that returned by the system shell after running command。

在unix和windows系统下其返回值是不一样的,unix下返回一个returncode,而非执行结果,windows下则返回执行结果。

 os.system('ls')

2. os.popen(cmd, mode='r', buffering=-1)

open a pipe to or from command cmd. the return value is an open file object connected to the pipe, which can be read or written depending on whether modeis 'r' (default) or 'w'。

为要执行的命令开一个pipe,返回值为此pipe(一般为一个打开的文件),mode参数即为打开模式,可以从此文件中读取返回的结果。

popen并不会等命令执行完毕,而是会直接返回一个pipe端对象,正如上边所说的,可以使用readlines等读取已经写入的内容。

例如:

tmp = os.popen('ls *.py').readlines()
# popen可以使用with上下文语法来处理:
in [9]: with os.popen('ls') as p:
   ...:     for l in p.readlines():
   ...:         print(l.strip('\n'))
popen的好处在于:将返回的结果存于临时文件中,便于程序处理。
system()与popen()的区别则在于,前者需要等命令执行完毕才返回,后者不会等子进程执行完毕,system()就相当于popen().wait(),后者也是返回returncode。
python3的官网已经说明了,os.popen是基于subprocess.popen实现的:this is implemented using subprocess.popen; 
而在python2.7的官方文档里说明了:deprecated since version 2.6,即此方法自2.6以来已经被放弃了。
因此建议,使用subprocess.popen来执行系统命令。

二、subprocess模块

os模块里还有很多其他重要的method,但是仅就执行系统命令来说,subprocess模块是这项功能的改进版。

subprocess主要是run()方法和popen()对象,前者在python3.5之前可能大多使用call(),在3.5之后使用run()来简化。

subprocess.run(args, *, stdin=none, input=none, stdout=none, stderr=none, capture_output=false, shell=false, cwd=none, timeout=none, check=false, encoding=none, errors=none, text=none, env=none, universal_newlines=none)

run the command described by args. wait for command to complete, then return a completedprocess instance.

即run():执行指定的命令,等待执行结束并返回一个completedprocess 实例对象。

import subprocess
subprocess.call (["cmd", "arg1", "arg2"],shell=true)

class subprocess.popen(args, bufsize=-1, executable=none, stdin=none, stdout=none, stderr=none, preexec_fn=none, close_fds=true, shell=false, cwd=none, env=none, universal_newlines=none, startupinfo=none, creationflags=0, restore_signals=true, start_new_session=false, pass_fds=(), *, encoding=none, errors=none, text=none)

execute a child program in a new process. on posix, the class uses os.execvp()-like behavior to execute the child program. on windows, the class uses the windows createprocess() function.

即popen():开启一个子进程执行命令。

run与popen的差别在于,前者是一个method,会在执行完命令然后返回一个包含returncode和所执行的命令的completedprocess对象,后者则只是建好子进程,想要获取结果就得使用此class的各种instance method。

在获取执行结果方面有些类似于os.system与os.popen的差别。

而popen class相对于os.popen的优势在于,popen是一个构造一个class instance,popen是一个method,一个instance显然具有更多的选项,可以帮助我们更好的控制子进程。

import subprocess
p = subprocess.popen('ls', shell=true, stdout=subprocess.pipe, stderr=subprocess.stdout)
for line in p.stdout.readlines():
    print(line)
retval = p.wait()
# popen对象支持with上下文写法:
with subprocess.popen('ls', shell=true, stdout=subprocess.pipe, stderr=subprocess.stdout) as p:
    for line in p.stdout.readlines():
        print(line)

最后:

1.当执行命令的参数或者返回中包含了中文字符,那么建议使用subprocess。
2.综上所述,还是建议使用subprocess.popen来执行系统命令,一方面popen相比os.system()和subprocess.run()是非阻塞模式的,另一方面popen相比os.popen()更加的灵活与全面,所以建议在执行操作系统命令时使用subprocess.popen对象,并同时推荐其with写法。