Python 内置模块 之 os、sys、subprocess
OS 用于提供系统级别的操作
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd os.curdir 返回当前目录: ('.') os.pardir 获取当前目录的父目录字符串名:('..') os.makedirs('dirname1/dirname2') 可生成多层递归目录 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.remove() 删除一个文件 os.rename("oldname","newname") 重命名文件/目录 os.stat('path/filename') 获取文件/目录信息 os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n" os.pathsep 输出用于分割文件路径的字符串 os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' os.system("bash command") 运行shell命令,直接显示 os.environ 获取系统环境变量 os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False os.path.isabs(path) 如果path是绝对路径,返回True os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 即 access time os.path.getctime(path) 返回path所指向的文件或者目录的属性修改时间 即 change time os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 即 motify time
sys 用于提供对解释器相关的操作
sys.argv[n] 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdin 标准输入,默认为键盘
sys.stdout 标准输出,默认为屏幕
sys.err 标准错误输出,默认为屏幕
>>> help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
>>> sys.stdout.write('hello')
hello5
输出重定向
>>> with open('out.log','w') as f:
print('test',file=f)
# cat out.log
test
>>> sys.stdin.readline()[:-1] # -1 to discard the '\n' in input stream
subprocess 系统命令操作
os.system , os.spawn* 可以执行shell命令 , subprocess 模块也可以执行命令并提供了更丰富的功能。
>>> help(subprocess) This module allows you to spawn processes, connect to their input/output/error pipes, and obtain their return codes. Main API ======== run(...): Runs a command, waits for it to complete, then returns a CompletedProcess instance. # 返回一个已经完成的子进程实例 Popen(...): A class for flexibly executing a command in a new process Constants --------- DEVNULL: Special value that indicates that os.devnull should be used PIPE: Special value that indicates a pipe should be created STDOUT: Special value that indicates that stderr should go to stdout Older API ========= call(...): Runs a command, waits for it to complete, then returns the return code. # 执行命令,返回状态码
>>> retcode= subprocess.call(['ls','-l'])
>>> retcode= subprocess.call('ls -l', shell=True) check_call(...): Same as call() but raises CalledProcessError() if return code is not 0 # 执行命令,如果执行状态码是 0 ,则返回0,否则抛异常
>>> retcode= subprocess.check_call(['ls','-l'])
>>> retcode= subprocess.check_call('ls -l', shell=True) check_output(...): Same as check_call() but returns the contents of stdout instead of a return code # 执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常
>>> subprocess.check_output('ls')
b'anaconda-ks.cfg\ndbbackup\nscripts\n' getoutput(...): Runs a command in the shell, waits for it to complete, then returns the output # 接收字符串格式命令,并返回结果
>>> subprocess.getoutput('ls')
'anaconda-ks.cfg\ndbbackup\nscripts'
getstatusoutput(...): Runs a command in the shell, waits for it to complete,
then returns a (status, output) tuple # 接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果
>>> subprocess.getstatusoutput('ls')
(0, 'anaconda-ks.cfg\ndbbackup\nscripts')
subprocess实例操作方法
poll() Check if child process has terminated. 没终止返回None,结束返回0
wait() Wait for child process to terminate. Returns returncode attribute.
communicate() 等待子进程结束,可以指定超时时间, 如communicate(timeout=3), 如果超过指定时间没结束,则抛出异常 TimeoutExpired: Command 'x' timed out after 3 seconds
terminate() 终止所启动进程
stdin 标准输入
stdout 标准输出
stderr 标准错误
pid The process ID of the child process.
returncode 子进程执行结束的返回码
注:使用 subprocess 模块的 Popen 调用外部程序,如果 stdout 或 stderr 参数是 pipe,并且程序输出超过操作的 pipe size时,如果使用 Popen.wait() 方式等待程序结束获取返回值,会导致死锁,程序卡在 wait() 调用上。 官方推荐使用 Popen.communicate()。这个方法会把输出放在内存,而不是管道里,所以这时候上限就和内存大小有关了,一般不会有问题。而且如果要获得程序返回值,可以在调用communicate() 之后取 returncode 的值。
subprocess.run 大多数情况下能满足需求
>>> obj=subprocess.run('ls -l /dev/null',shell=True) crw-rw-rw- 1 root root 1, 3 Oct 18 2016 /dev/null >>> print(obj) CompletedProcess(args='ls -l /dev/null', returncode=0) >>> obj=subprocess.run('ls -l /dev/null',shell=True,stdout=subprocess.PIPE) >>> obj.stdout b'crw-rw-rw- 1 root root 1, 3 Oct 18 2016 /dev/null\n'
subprocess.Popen
Popen更强大,可以与执行的命令或启动的子进程进行交互
# python 进入python交互
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# pstree |grep python
| `-sshd---bash---python---python # 可以看到Popen fork出一个python子进程
>>> obj.pid #查看子进程的id
14552
父进程和子进程之间可以通过管道通信 ,subprocess.PIPE
![](https://images2015.cnblogs.com/blog/1162514/201706/1162514-20170618142417634-281828288.png)
Popen 常用参数:
- args:shell命令,可以是字符串或者序列类型(如:list,元组)
- shell:True, False(默认) ,设置为True 表示以字符串形式接收命令
- bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
- cwd:用于设置子进程的当前目录
- stdin, stdout, stderr:分别表示程序的标准输入、标准输出、标准错误输出,可以是 subprocess.PIPE 或 其他程序、文件。
- env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
- universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
- preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
>>> cmd='ifconfig'
>>> obj=subprocess.Popen(args=cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.stdout.read()
>>> obj=subprocess.Popen('cat >> test.txt',shell=True,stdin=subprocess.PIPE) >>> obj.stdin.write(b'1st line \n') # 通过管道输出或写入到 cat子进程,因为cat写入的是文件,所以要将字符串转换成byte >>> obj.stdin.write(b'2nd line \n') >>> obj.stdin.write(b'3rd line \n') >>> obj.stdin.close() # 关闭管道输入,此时cat执行结束 >>> subprocess.getoutput('cat test.txt') '1st line \n2nd line \n3rd line '
>>> obj=subprocess.Popen('uname -n',shell=True,stdout=subprocess.PIPE)
>>> obj.stdout.read() # 通过管道将 uname -n 的执行结果读出, stdin 和 stdout都是一个管道文件对象,所以需要write(),read()等操作方法写入或读出
b'VM_200_111_centos\n'
>>> obj=subprocess.Popen('uname -n',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.wait()
0
>>> obj.communicate() # returns a tuple (stdoutdata, stderrdata). 返回一个元组
(b'VM_200_111_centos\n', None)
>>> obj=subprocess.Popen('xxx',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.communicate()
(b'', b'/bin/sh: xxx: command not found\n')
>>> obj=subprocess.Popen('top -bn 10',shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT
>>> obj.wait() # 卡死
>>> obj.communicate()
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write("print('welcome to python3')\n")
>>> obj.stdin.close()
>>> obj.stdout.read()
'welcome to python3\n'
>>> obj.stdout.close()
>>> obj.stdout.read()
ValueError: I/O operation on closed file. #管道已经关闭
这里不知道为什么不使用 universal_newlines=True 就会出如下异常
TypeError: a bytes-like object is required, not 'str