系统编程概述
系统编程概述
主要集中在介绍sys和os模块,sys模块负责导出与python解释器本身相关的组件,os则包含与python所在底层操作系统相对应的变量和函数。
一、获取模块文档
import sys
dir(sys) #显示模块属性
help(sys) #获取模块的帮助信息
使用程序的两种方
1、导入运行
在统一进程中加载运行代码,生成模块对象,运行较快。
2、命令行启动执行
启动独立的进程运行
sys模块
sys.path #模块搜索路径
sys.modules #已加载的模块
sys.getrefcount #对象引用次数
sys.argv #命令行参数
sys.stdout #标准流
sys.stdin
sys.stderr
os模块
该模块提供了POSIX工具,操作系统调用的跨平台移植标准。
os.getpid() #给出调用函数的进程ID
os.path #目录处理相关工具
os.system #运行shell命令,阻塞式。
os.popen #运行shell命令,可实现标准流控制,非阻塞。
os.subprocess #复杂流控制
管道对象
封装了_iter_方法,支持迭代,可实现进程间的通信。
二、脚本运行上下文
CWD、文件、import路径
python会把脚本所在路径添加到模块搜索路径的最前面
命令行参数
sys.argv
解析命令行参数
使用getopt、optparse等模块
shell环境变量
os.environ
一个子程序始终从它的父进程那里继承环境变量。
标准流
标准流是预先打开的python对象,在python启动时自动连接到程序里,默认是被绑定在控制台窗口。
linux shell下标准流的用法
(1)shell作为init的一个子进程,是操作提供提供给用户的交互接口,当shell被启动之后,标准输入就被绑定在shell窗口的控制台。
(2)shell环境下执行shell命令,该命令以单独的进程运行,其执行结果应由执行命名控制,标准输出和标准错误可被指定到文件、控制台或管道等。
例:
wget -SO /dev/null http://url 2>/dev/null
执行该命名之后,标准错误会被重定向到/dev/null。
(3)管道
将标准输出绑定到管道文件,并且将下一个程序的标准输入绑定到这个管道文件,从而实现进程之间的通信。
例:
echo "1" |xargs echo ;echo 1
(4)标准输入,标准输出、标准错误
这三个标准流对应于系统0,1,2这三个文件描述符。
标准流的接口
echo #linux中典型的标准输出接口
read #linux中典型的标准输入接口,按行读取识别\n。
input #python中典型的标准输入接口,按行读取识别\n。
print #python中典型的标准输出接口
实例讲解
#teststream.py
#读取标准输入,再进行处理
1 def interact(): 2 print('Hello stream world') 3 4 while True: 5 try: 6 reply = input('Enter a number>') 7 except EOFError: 8 break 9 else: 10 num = int(reply) 11 print("%d squared is %d" % (num, num ** 2)) 12 print('Bye') 13 14 if __name__ == '__main__': 15 interact() 16 17 #more.py实现分页显示 18 def more(text, numlines=15): 19 lines = text.splitlines() 20 while lines: 21 chunk = lines[:numlines] 22 lines = lines[numlines:] 23 for line in chunk: 24 print(line) 25 if lines and input('more?') not in ['x', 'y']: break 26 27 if __name__ == '__main__': 28 import sys 29 print(sys.stdin) 30 #more(open(sys.argv[1]).read(), 10) #该输入对象需要支持文件对象打开的方法 31 more(sys.stdin.read(), 10)
命令行执行
python teststream.py < input.txt | python more.py
该命令在执行时,如果teststream.py输出的信息过多的话,会导致more.py文件执行异常。
异常解析
teststream.py在执行时以input.txt为标准输入,标准输出被重定向到管道文件,more.py文件的标准输入文件被重定向到管道中,
当more.py需要进行分页判断的时候,无法从控制台捕获用户的输入,会直接从管道文件读取,这时执行会出现异常。
处理办法
在more.py文件需要从控制台捕获用户输入的时候,可以先检查下当前的stdin是否被绑定在控制中。
重定向流到python对象
标准流的重定向不仅仅能够在shell环境下使用,可以在任何语言中实现,包括python:
>>提供任何类似于文件read方法的对象可以指定给sys.stdin
>>提供任何类似于文件write方法的对象可以指定给sys.stdout
print,input只是简单的调用sys.stdin或sys.stdout对象的read或write方法,而sys.stdin和sys.stdout是直接与标准流对应的。
标准流重定义python对象的实例:
1 import sys 2 class Output: 3 def __init__(self): 4 self.text = '' 5 def write(self, string): 6 self.text += string #追加写 7 def writelines(self, lines): #提供列表对象,迭代写入 8 for line in lines: self.write(line) 9 class Input: 10 def __init__(self, input=''): #初始化输入流对象 11 self.text = input 12 def read(self, size=None): #按直接读取 13 if size == None: #默认全部读取 14 res, self.text = self.text, '' 15 else: 16 res, self.text = self.text[:size], self.text[size:] 17 return res 18 def readlines(self): #按行读取 19 eoln = self.text.find('\n') #根据\n来定位字符索引位置,根据索引来读取 20 if eoln == -1: 21 res, self,text = self.text, '' 22 else: 23 res, self.text = self.text[:eoln+1], self.text[eoln+1:] 24 class redirect(function, pargs, kargs, input): 25 savesteams = sys.stdin, sys.stdout 26 sys.stdin = Input(input) #重定向流到python输入和输出对象 27 sys.stdout = Output() 28 try: 29 result = function(*pargs, *kargs) 30 output = sys.stdout.text #获取标准输出文本 31 finally: 32 sys.stdin, sys.stdout = savesteams #重置输入输出流 33 return result, output 34 35 if __name__ == '__main__': 36 (result, output) = redirect(interact, (), {}, '4\n5\n6\n') 37 print(result) 38
实用案例
可利用输入和输出重定向到python对象的机制,实现GUI程序的输入和输出弹窗信息输出。
三、实用工具类io.String和io.BytesIO
该工具类提供了一个对象,将一个文件对象接口和内存字符串相映射:
>>from io import StringIO
>>buff =StringIO()
>>buff.write('spam\n')
>>buff.getvalue()
>>buff =StringIO('spam\n')
>>buff.readline()
#字节使用参照以上用法
捕获stderr流
在python中使用sys.stderr.write()函数即可
print函数中使用重定向
print(stuff, file=afile) #原生支持流重定向,一次性的
其他重定向选项:os.popen和子进程
os.popen
subprocess.Popen
它们可以在python程序内部重定向另外一个程序的流,可实现读取另一个程序的输出,类似于shell中管道的功能。
作用范围仅在启动的子程序中使用。
为生成程序的标准输入流提供输入
>>pipe = os.popen('python hello-in.py', 'w') #对stdin进行写操作,默认是对stdout进行读操作
>>pipe.write('spam\n') #可实现对另一程序的输入控制
>>pipe.close()
>>open('hello-in.txt').read()
利用subprocess重定义输入和输出
更细粒度地控制生成程序的流,并实现双向通信(访问一个程序的输入和输出),将一个程序的输出发送到另一程序的输入。
示例:
pipe = Popen('python reader.py', stdin=PIPE, stdout=PIPE)
pipe.stdin.write(b'Lumberjack\n') #写入标准输入
pipe.stdin.close()
output = pipe.stdout.read() #读取标准输出
pipe.wait()
print(output)
以上示例在一个终端console上启动一个子程序并获取到了这个子程序的输出信息。
比较
os.popen实现的管道只能读或者写,处于单工运行状态,我们无法在代码中获取第二个脚本的输出。
import os
p1 = os.popen('python reader.py', 'r') #为标准输出提供输出管道(读操作)
p2 = os.popen('python writer.py', 'w') #为标准输入提供输入管道(写操作)
p2.write(p1.read()) #将p1的输出信息重定向到p2的输入
x = p2.close() #该步骤无法获取p2的输出信息,默认打印在console上
print(x)