python的sys模块剖析
python的sys模块剖析
前言
由于最近一直在练习编写一些基本的端口扫描工具,虽然很多工具早就已经成熟,我们也不必再造轮子,但是其中的基本原理我们还是要了解和学习一些的,毕竟不能只做“脚本小子”,正如我所认为的一个正确的学习过程应该是这样的:使用—>模仿—>超越。我觉得这也是安全开发所应该经历的过程。从使用别人的工具,到模仿制作相似的工具,再到实现自己独特的想法。所以,学好这些基本模块的使用是很重要的,废话不多说了,直接开始。
环境
python——>3.8
windows
简要
sys模块是python自带的模块,无需另外安装,内置了许多函数,我们通过调用这些内置模块函数可以实现很多我们需要的功能,最常见的比如说参数的传递,异常的处理等等。
sys常用方法文档:
方法 | 说明 |
---|---|
sys.argv | 接收命令行的参数,是一个列表,第一个元素是文件本身 |
sys.exit([arg]) | 程序退出,arg表示退出状态,默认为0,arg为0视为成功终止,否则为异常终止 |
sys.modules | 输出当前程序加载的模块 |
sys.path | List,指定模块搜索路径,初始化是python的环境变量 |
sys.platform | 平台操作系统的名称 |
sys.stdin | 标准输入流 |
sys.stdout | 标准输出流 |
sys.stderr | 标准错误流,就是专门用来输出错误的 |
sys.exc_info() | 给出当前正在处理的异常的信息。返回的信息仅限于当前线程和当前堆栈帧 |
sys.exc_clear() | 清除当前正在处理的异常的信息 |
详细介绍
下面我们来通过代码实际了解一下,毕竟看文字不如动手敲代码来的实在
sys.argv
这个方法是用来传参的,通常我们编写完脚本时候有些形参是需要从外部传入的。
def demo(p0, p1, p2):
print('这是自带的第一个参数:', p0)
print('这是输入的第一个参数:', p1)
print('这是输入的第二个参数:', p2)
if __name__ == '__main__':
import sys
demo(sys.argv[0], sys.argv[1], sys.argv[2])
运行结果:
>python 1.py First Second
这是自带的第一个参数: 1.py
这是输入的第一个参数: First
这是输入的第二个参数: Second
可见上面要注意输入的第一个参数是从argv[1]
开始的
sys.stdin
标准输入流,其实已经解释的较为清楚,这个是接收我们输入的,并且是接收一串输入,功能类似input()
函数
def demo(p):
print('这是接收的输入流:', p)
if __name__ == '__main__':
import sys
test = sys.stdin.readline()
demo(test)
运行结果:
>python 1.py
www.jlx-love.com
这是接收的输入流: www.jlx-love.com
sys.stdin
只是接收了我们的键盘输入,但不具备赋值的功能,所以如果想要把输入的值赋值给test
,那么我们还需要用到readline
,即读取接收的输入流
sys.stdout
说完了输入,那我们就紧接着说一说输出,所谓标准输出,即将值输出而已
def demo():
sys.stdout.write('www.jlx-love.com')
sys.stdout = open('out.txt', 'w')
print('My blog is: www.jlx-love.com')
if __name__ == '__main__':
import sys
demo()
简单解释一下,我们可以看到,我demo
函数里有两个sys.stdout
这是两种用法,第一个就是我们向输出流中写入东西,然后它给输出,功能和print
是相似的,不同的是,它只能接收str
类型。第二个是什么意思呢?就是说,我把我的输出流送到一个叫out.txt
文件,以写的方式打开,然后下面紧接着我输出了一段字符串,那么这段字符串就是输出流,这个输出流就会写到out.txt
文件中。这个长用在日志访问输出中。
运行结果:
>python 1.py
www.jlx-love.com
可以看到,我们print
输出的内容没有在终端显示,而是直接写到了out.txt
文件中
sys.stderr
def demo():
sys.stderr.write('This is a error')
sys.stderr = open('out.txt', 'w')
sys.stderr.write('This is a redirect error~')
if __name__ == '__main__':
import sys
demo()
跟上一个差不多,这里不再过多阐述,第一个会回显到终端上,第二个则是写到out.txt
文件中
运行结果:
>python 1.py
This is a error
sys.path
def demo():
print(sys.path)
if __name__ == '__main__':
import sys
demo()
运行结果:
>python 1.py
['E:\\Python代码', 'D:\\Python38\\python38.zip', 'D:\\Python38\\DLLs', 'D:\\Python38\\lib', 'D:\\Python38', 'D:\\Python38\\lib\\site-packages', 'D:\\Python38\\lib\\site-packages\\wafw00f-2.1.0-py3.8.egg', 'D:\\Python38\\lib\\site-packa
ges\\pluginbase-1.0.0-py3.8.egg', 'D:\\Python38\\lib\\site-packages\\requests-2.23.0-py3.8.egg', 'D:\\Python38\\lib\\site-packages\\pysocks-1.7.1-py3.8.egg', 'D:\\Python38\\lib\\site-packages\\urllib3-1.25.9-py3.8.egg', 'D:\\Python38\\
lib\\site-packages\\idna-2.9-py3.8.egg', 'D:\\Python38\\lib\\site-packages\\chardet-3.0.4-py3.8.egg', 'D:\\Python38\\lib\\site-packages\\certifi-2020.4.5.1-py3.8.egg']
输出形式是一个列表,初始化则是python的环境变量,我的python是安装在Dpan,代码写在E盘,我们也可以看到它搜索的顺序,是现在当前目录寻找,然后再去python的环境变量中前去寻找
sys.exit([argv])
从名字就知道干啥的啦,退出程序,只不过这个退出也是有不同情况的,有的是正常退出,有的是非正常退出。所以这里就多了一个参数,那么不同参数有什么不同呢?多数系统要求该值的范围是 0--127,否则会产生不确定的结果。某些系统为退出代码约定了特定的含义,但通常尚不完善;Unix 程序通常用 2 表示命令行语法错误,用 1 表示所有其他类型的错误。传入其他类型的对象,如果传入 None
等同于传入 0,如果传入其他对象则将其打印至 stderr
,且退出代码为 1。所以我们了解了,不同的参数代表不同的错误类型和退出程序,当然如果是0的话就是正常退出lou,那这个怎么用呢?接下来给大家看看两个不同代码执行结果,来充分理解一下。
def demo():
try:
sys.exit(0)
except:
print('www.jlx-love.com')
if __name__ == '__main__':
import sys
demo()
运行结果:
>python 1.py
www.jlx-love.com
def demo():
sys.exit(0)
print('www.jlx-love.com')
if __name__ == '__main__':
import sys
demo()
运行结果:
>python 1.py
结果很明显,可以看到第二个什么也没有输出,通过这两个结果的对比,我们可以更深刻的理解一下exit
的原理。当调用exit
之后,会抛出一个异常,如果这个异常被捕获,则下面的代码会继续执行,反之,若异常没有被捕获,则会直接退出python解释器
sys.exc_info()
捕获异常,有时候在某些场景下,只捕获异常是不够的,我们还需要捕获异常的详细信息,那么这个时候exc_info()
就排上用场了。这里正好借助上面exit
抛出一个异常
def demo():
try:
sys.exit(0)
except:
print(sys.exc_info())
if __name__ == '__main__':
import sys
demo()
运行结果:
>python 1.py
(<class 'SystemExit'>, SystemExit(0), <traceback object at 0x0000014E8C7F4280>)
看到捕获到异常之后,输出了异常的详细信息,这是一个元组,里面有3个元素,第一个元素是一个SystemExit
类,第二个元素是SystemExit
类的一个实例,第三个元素给出了一个内存地址,但是看不到详细信息,如果想要看到详细信息,就需要使用traceback
模块中的print_tb
方法
import traceback
def demo():
try:
sys.exit(0)
except:
traceback.print_tb(sys.exc_info()[2])
if __name__ == '__main__':
import sys
demo()
运行结果:
>python 1.py
File "1.py", line 5, in demo
sys.exit(0)
可以看到输出了文件名,第几行,哪个位置出现了错误,更为详细。