python学习笔记07:系统命令&环境变量
1. 使用subprocess.Popen()
调用命令:
import subprocess
proc=subprocess.Popen(
'ls .vim*', # 待执行的命令
shell=True, # 使用shell
cwd='/home/g00444054', # 到这个目录去执行命令
stderr=subprocess.PIPE,# 执行命令后的报错信息送到pipe(默认打印到stderr)
# 可以通过p.stderr访问该pipe内容;
stdout=subprocess.PIPE,# 执行命令后的输出信息送到pipe(默认打印到stdout)
# 可以通过p.stdout访问该pipe内容
)
等待子进程结束;
使用wait()等待子进程结束,有可能导致死锁,不建议使用wait(), 建议使用communicate()
print(proc.returncode) # 如果为None,表示子进程还未结束
p.wait() # 等待子进程结束,但PIPE太大时它可能导致死锁。
~~print(proc.returncode) # 为0,表示子进程正常退出 ~~
建议使用communicate()等待子进程结束,不会死锁。
print(proc.returncode) # 如果None,表示子进程还未结束
b_stdout, b_stderr = proc.communicate() # 等待子进程结束,返回bytes
print(proc.returncode) # 为0,表示子进程正常退出
查看命令的标准输出:
# b_stdout是二进制str, 需要decode, windows下使用gbk
for s_line in b_stdout.decode('gbk').strip().split('\n'):
print(s_line)
.viminfo
.vimrc
.vim
plugin
syntax
查看命令的标准错误
for s_line in b_stderr.decode('gbk').strip().split('\n')
print(s_line)
#如果cmd改成dir .vimx*,s_line就是:
#找不到文件
另外, 在proc.communicate()前可以通过proc.stdout/proc.stderr来获取stdout和stderr, 但proc.communicate()后会报告io buffer已经关闭了(它们是被当作io对象来访问的).
for b_line in proc.stdout:
print(b_line.decode('gbk').strip())
for b_line in proc.stderr:
print(b_line.decode('gbk').strip())
2. 使用os.system和os.popen
os.system(cmd)可以得到cmd的返回值(即shell的exit值),而不是命令的输出
>>> value = os.system('ls') #会在Termianl打印命令的输出
file0 dir0
file1 dir1
>>> value #value得到的是命令的返回值,即shell的exit值,而不是命令的输出;
0
os.popen()可以得到命令的输出,返回执行后的信息对象, 通过管道将结果返回;
语法: os.popen(command, [, mode, buffering])
参数1:command :调用的命令;
参数2:mode :返回file对象的模式,默认为"r",只读模式;
参数3:buffering:缓冲区大小,默认-1,无限制;
>>> pipeline = os.popen('ls')
>>> for line in pipeline.readlines():
... print(line.strip())
...
dir0
dir1
file0
file1
3. 获取系统平台名
Windows对应'nt',Limux/Unix对应'posix';
>>> os.name
'posix'
4. 获取用户名
>>> import getpass
>>> getpass.getuser()
'g004440**'
5. 操作环境变量
5.1. os.environ
>>> import os
>>> type(os.environ)
<class 'os._Environ'>
>>>
>>> for k, v in os.environ.items(): # 可以把os.environ当作dict访问
... print('{k:<10} = {v}'.format(k=k, v=v))
...
LANG= C
USER= g004440**
HOME= /home/g004440**
...
>>> os.environ['USER'] # 直接通过key查变量值
'g004440**'
>>> os.environ.get('USER') # 使用get()通过key查变量值
'g004440**'
>>> os.environ['CELL_CNT'] # 查不存在的key会报错
KeyError: 'CELL_CNT'
>>> os.environ.get('CELL_CNT', 0) # 通过get()指定返回值,默认为None
0
>>> os.environ['CELL_CNT'] = str(99) # 通过赋值运算修改或添加环境变量,int会报错
>>> os.environ['CELL_CNT'] # CELL_CNT环境变量已经添加
'99'
>>> os.environ.get('CELL_CNT', 0) # 使用get()也可以得到
'99'
5.2. os.getenv()、os.putenv()
注意:通过putenv()设置的环境变量,使用getenv()无法获取,使用os.environ[]也无法获取(即没有修改os.environ的值),它只能是默默地修改了环境变量?
os.getenv(key, default=None) 获取环境变量
os.putenv(name, value, /) 设置环境变量name=value,value必须是str、bytes或os.PathLike obj,不能是int
>>> import os
>>> os.getenv('USER') # 获取环境变量'USER'
'g004440**'
>>> os.getenv('CELL_CNT', 0) # 获取不存在的环境变量,指定返回值
0
>>> os.putenv('CELL_CNT', str(99))
>>> os.getenv('CELL_CNT', 0) # putenv()设置的key,不能使用getenv()获得
0
>>> os.environ.get('CELL_CNT', 0) # os.environ也没有改变
0
6. 修改python搜索模块的路径集
sys.path是一个list,内容为python搜索模块的路径;
- 临时修改:可以在python程序中修改sys.path: sys.path.append('xxx'),但程序退出后这个修改会消失。
- 固定修改:如果要永久地修改sys.path,需要设置PYTHONPATH这个环境变量,不同路径使用冒号分开;
>>> import sys
>>> [print(f'"{x}"') for x in sys.path]
""
"/data/XX/code/lib/python"
"/software/xx/lib/python3.6"
7. 标准输入、标准输出、标准错误
7.1. sys.stdin()
sys.stdin.readline()与input()的区别
>>> import sys
>>> s0 = input('Enter string 0: ') # python2中是raw_input()
Enter string 0: abc # 获取用户输入
>>> s0 # input()函数会去掉换行符
'abc'
>>>
>>> s1 = sys.stdin.readline() # 这里不能给str参数,它的参数是str长度;
abc
>>> s1 # 会将换行符一并获取
'abc\n'
>>> s2 = sys.stdin.readline()[:-1] # 切片,去掉最后一个元素
abc
>>> s2 # s2结尾没有换行符,已经去掉;
'abc'
7.2. sys.stdout()
sys.stdout.write()与print()的区别
>>> import sys
>>> print('abc')
abc
>>> n = sys.stdout.write('abc'+'\n') # 函数返回string的长度
abc
>>> n
4
>>> n= sys.stdout.write('abc' + os.lineseq) # 打印后加换行
abc
>>> os.linesep
'\n'
os.linesep获取当前平台的行终止符,str类型,Windows使用'\r\n',Linux使用'\n',Mac使用'\r'
使用sys.stdout.flush(),把写缓冲区的内容冲到标准输出,不然不能实时显示内容
>>> import sys, time
>>> for i in range(5):
... for j in range(5):
... time.sleep(0.5)
... print('*', end='')
... sys.stdout.flush() # flush write buffers,在print后使用
... print('')
...
*****
*****
*****
*****
*****
7.3. sys.stderr()
可以把print的内容输出到标准输出
>>> import sys
>>> print('abc', sys.stderr)
abc <_io.TextIOWrapper name='<stderr>' mode='w' encoding='ANSI_X3.4-1968'>