【Python】python脚本实例
python脚本的实例
本⽂通过⼀个简单的python脚本实例,来介绍python语法。
参数:ip地址,端⼝号port
需求:
1. ⾸先进⾏ping,如果ping不成功就就进⾏traceroute
2. 如果ping得通就⾏telnet
3. traceroute的结果要输出最后⼀跳的地址
4. telnet如果成功输出成功,不成功且失败信息报refused则输出“端⼝未开启”,如果不成功且失败信息没有报refused则报访问不通
5. 需要进⾏⼀个ip校验,看是否符合格式
1.⾸先编写ip地址检验的⽅法
import sys
import re
def checkIp(host):
ip = host
# 检验ip地址中的正则
res = re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ip)
if res:
print ("ip is ok")
return 0
else:
print ("ip is error")
return 1
ip地址的检验逻辑⾮常简单,只要⽤正则表达式就可以。这⾥介绍⼀下python正则中的“原始字符串”功能。
反斜杠,在Python中⽐较特殊,就是它可以⽤来构成⼀些特殊字符,⽐如“\n”表⽰换⾏,“\t”表⽰制表符。下⾯是使⽤“\n”的⼀⾏代码:
>>>print ('Hello\World\nPython' )
结果为:
“Hello\World
Python“
可以看到其中的“\n”已转义为换⾏符,⽽“\W”没有发⽣转义,原因是“\W”在“字符串转义”中并不对应着特殊字符,没有特殊含义。
如果现在要求变了,要求不对“\n”转义为换⾏,⽽是原封不动输出为“Hello\World\nPython”,该怎么办呢?
1)可以这样写“Hello\World\nPython”,这样输出的时候,“字符串转义”会把“\”转义为“\”;
2)也可使⽤另⼀种⽅法:原始字符串;原始字符串(即r’…’):字符串中所有字符都直接按照字⾯意思来使⽤,不转义特殊字符。
下⾯是使⽤原始字符串的代码:
print r'Hello\World\nPython'
结果为:
“Hello\World\nPython”
可以清楚看到,在使⽤原始字符串之后,“\n”未被转义为换⾏符,⽽是直接被输出了。
1.1正则转义
上⾯讲的只是“字符串转义”。同理,在正则表达式中也存在转义,称其为“正则转义”,其与“字符串转义”完全不同,⽐如“\d”代表数字,“\s”代表空⽩符。下⾯我们先编写开头的例⼦,然后再分析。
需求:提取“3\8”反斜杠之前的数字:
import re
string = '3\8'
m = re.search('(\d+)\\\\', string)
if m is not None:
up(1) # 结果为:3
n = re.search(r'(\d+)\\', string)
if n is not None:
up(1) # 结果为:3
正则表达式字符串需要经过两次转义,这两次分别是上⾯的“字符串转义”和“正则转义”,个⼈认为“字符串转义”⼀定先于“正则转义”。
1)’\\\\'的过程:
先进⾏“字符串转义”,前两个反斜杠和后两个反斜杠分别被转义成了⼀个反斜杠;即“\|\”被转成了“\|\”(“|”为⽅便看清,请⾃动忽略)。“字符串转义”后马上进⾏“正则转义”,“\\”被转义为了“\”,表⽰该正则式需要匹配⼀个反斜杠。
2)r’\\'的过程:
由于原始字符串中所有字符直接按照字⾯意思来使⽤,不转义特殊字符,故不做“字符串转义”,直接进⼊第⼆步“正则转义”,在正则转义中“\\”被转义为了“\”,表⽰该正则式需要匹配⼀个反斜杠。
也就是说原始字符串(即r’…’)与“正则转义”毫⽆关系,原始字符串仅在“字符串转义”中起作⽤,使字符串免去⼀次转义。
我们再来看这个检验ip地址的正则表达式
r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
⽤圆括号将所有选择项括起来,相邻的选择项之间⽤|分隔,表⽰可以匹配25[0-5]或者2[0-4][0-9]或者[01]?[0-9][0-9]?,第⼀个就是250~255,第⼆个是200-249,第三个稍微复杂,?表⽰匹配0次或者1次前⾯的字符串,表⽰0-199。同时^表⽰匹配开头,配合{3}表⽰匹配3次,表⽰前⾯三个字符串为0.0.0.到255.255.255.。最后⼀个字符串⽤$匹配结尾。但⽤圆括号会有⼀个副作⽤,使相关的匹配会被缓存,
导致匹配出现问题。此时可⽤?:放在第⼀个选项前来消除这种副作⽤。
因此该正则表达式的作⽤就是匹配0.0.0.0~255.255.255.255
def trace(host):
cmd = "traceroute {}".format(host)
# 创建⼀个subproess实例
p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
result = adlines() # 读取输出
print(type(result)) # 查看类型
out = result[-1] # 取得最后⼀跳地址的string
res = out.split() # 将最后⼀跳的string按照空格分隔
print (res[2])
return res[2]
可以看到这⾥使⽤了⼀个subprocess模块的使⽤,允许你去创建⼀个新的进程让其执⾏另外的程序,并与它进⾏通信,获取标准的输⼊、标准输出、标准错误以及返回码等。
2.1Popen类
subprocess模块中定义了⼀个Popen类,通过它可以来创建进程,并与其进⾏复杂的交互。我们可以⽤它来调⽤shell来在Linux系统中进⾏交互,查看⼀下它的构造函数:
__init__(self, args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None,
creationflags=0)
主要参数说明:
1. args:args should be a string, or a sequence of program arguments.也就是说必须是⼀个字符串或者序列类型(如:字符
串、list、元组),⽤于指定进程的可执⾏⽂件及其参数。如果是⼀个序列类型参数,则序列的第⼀个元素通常都必须是⼀个可执⾏⽂件的路径。当然也可以使⽤executeable参数来指定可执⾏⽂件的路径。
python新手代码例子2. stdin,stdout,stderr:分别表⽰程序的标准输⼊、标准输出、标准错误。有效的值可以是PIPE,存在的⽂件描述符,存在的⽂件对象
或None,如果为None需从⽗进程继承过来,stdout可以是PIPE,表⽰对⼦进程创建⼀个管道,stderr可以是STDOUT,表⽰标准错误数据应该从应⽤程序中捕获并作为标准输出流stdout的⽂件句柄。
3. shell:如果这个参数被设置为True,程序将通过shell来执⾏。
4. env:它描述的是⼦进程的环境变量。如果为None,⼦进程的环境变量将从⽗进程继承⽽来。
创建Popen类的实例对象
1. res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
2. cmd:标准像⼦进程传⼊需要执⾏的shell命令,如:ls -al
3. subprocess.PIPE:在创建Popen对象时,subprocess.PIPE可以初始化为stdin, stdout 或stderr的参数,表⽰与⼦进程通信的标
准输⼊流,标准输出流以及标准错误
4. subprocess.STDOUT:作为Popen对象的stderr的参数,表⽰将标准错误通过标准输出流输出。
因此我们可以看到p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
中调⽤shell的命令来执⾏
利⽤type⽅法来判断result的类型,其中readlines()返回的是shell执⾏结果的list形式,⼆read()或者readline()返回的是string类型。我们需要得到traceroute的最后⼀跳结果,因此需要list类型的result,使⽤[-1]的切⽚来得到list的最后⼀个元素
result = adlines() #返回⼀个list
print(type(result))
输出结果
traceroute to 192.168.229.2 (192.168.229.2), 30 hops max, 60 byte packets
1 192.168.229.1
2 192.168.229.2
3 192.168.229.3
4 192.168.229.4
5 192.168.229.5
out = result[-1]
输出结果
5 192.168.229.5
def do_telnet(Host, port):
cmd = "telnet {} {}".format(Host,port)
out = statusoutput(cmd) # 输出的是元组
print out
index = out.index(256)
# 如果返回的结果中没有256,则证明返回码不是256,证明telnet成功
if(index < 0):
print ("telnet成功")
# 如果telnet失败,且失败信息报refused,则输出检查机构端⼝
elif(out[1].find('refused') > -1):
print ("机构端⼝未开启,请检查贵司端⼝是否启⽤")
# 如果失败信息没有报refused,则需要进⾏traceroute
else:
print ("Telnet不通,访问结果:xxx")
3.ping函数的编写
def pingIp(host):
ip = host
res = checkIp(ip)
if res:
return 1
else:
backinfo = os.system('ping -c 5 -w 1 %s' % ip)
# 如果ping不通,进⼊traceroute
if backinfo:
lastHop = trace(ip)
print ("⽹络访问不通,traceroute最后⼀跳地址为{}".format(lastHop))
# 如果ping通进⾏telnet
else:
do_telnet(ip,port)
这⾥介绍第三个可以调⽤shell的python模块,就是os.system,执⾏该函数的时候会把信息直接打印出来。并且我们⽆法以数据结构的形式保存结果,因此对于需要后续逻辑判断的函数就不适⽤了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论