Prthon多线程和模块

  1. 案例1:简化除法判断
  2. 案例2:分析apache访问日志
  3. 案例3:扫描存活主机
  4. 案例4:利用多线程实现ssh并发访问

1 案例1:简化除法判断

1.1 问题

编写mydiv.py脚本,主要要求如下:

  • 提示用户输入一个数字作为除数
  • 如果用户按下Ctrl+C或Ctrl+D则退出程序
  • 如果用户输入非数字字符,提示用户应该输入数字
  • 如果用户输入0,提示用户0不能作为除数

1.2 方案

使用if语句判断除数是否合适,需要编写多条语句。有了异常处理,可以本着先做,错了再说的逻辑。直接把除法操作放在try语句中执行,根据产生的异常做相应的处理。

另外,Ctrl+C或Ctrl+D只能通过异常捕获。

异常捕获的语法如下:

  1. try:
  2. A
  3. except:
  4. B
  5. else:
  6. C
  7. finally:
  8. D

把可能发生异常的语句放在A里面执行,如果出现异常则执行B语句,没有异常则执行C语句。不管是否出现异常都会执行D语句。

捕获异常时,可以使用多个except语句,每个except语句捕获一个异常,每个异常给定不同的处理方法。也可以把多个异常放在同一个except语句后面,但是务必注意,多个异常写在相同的一行,一定要注括号括起来,放在元组中。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写脚本

  1. #!/usr/bin/env python
  2. import  sys
  3. while True:
  4. try:
  5. result = 100 / int(raw_input('enter a number: '))
  6. except (ValueError, ZeroDivisionError), e:   #将异常原因保存在变量e中
  7. print "invalid input:", e
  8. continue
  9. except  (EOFError, KeyboardInterrupt):
  10. sys.exit(1)
  11. break
  12. print  result

步骤二:测试脚本执行

  1. [root@py01 bin]# ./mydiv.py
  2. enter a number: 0
  3. invalid input: integer division or modulo by zero
  4. enter a number: abc
  5. invalid input: invalid literal for int() with base 10: 'abc'
  6. enter a number: 3
  7. 33

案例2:分析apache访问日志

2.1 问题

编写用于分析apache日志的脚本,主要要求如下:

  • 统计每个客户端访问apache服务器的次数
  • 将统计信息通过字典的方式显示出来
  • 分别统计客户端是Firefox和MSIE的访问次数
  • 分别使用函数式编程和面向对象编程的方式实现

2.2 方案

涉及到文本处理时,正则表达式将是一个非常强大的工具。匹配客户端的IP地址,可以使用正则表达式的元字符,匹配字符串可以直接使用字符的表面含义。

入门级程序员的写法,使用顺序的结构,直接编写。这种方法虽然可以得出结果,但是代码难以重用。参考步骤一。

进阶的写法可以采用函数式编程,方便日后再次使用。参考步骤二。

最后,还可以使用OOP的编程方法,先定义一个统计类,该类将正则表达式作为它的数据属性。再定义一个方法,从指定的文件中搜索正则表达式出现的次数,并将其存入到一个字典中。参考步骤三。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:简单实现

  1. [root@py01 bin]# vim countweb.py
  2. #!/usr/bin/env python
  3. import re
  4. logfile = '/var/log/httpd/access_log'
  5. cDict = {}
  6. patt_ip = '^\d+\.\d+\.\d+\.\d+'         #定义匹配IP地址的正则表达式
  7. with open(logfile) as f:
  8. for eachLine in f:
  9. m = re.search(patt_ip, eachLine)
  10. if m is not None:
  11. ipaddr = m.group()
  12. #如果IP地址已在字典中,将其值加1,否则初始值设置为1
  13. cDict[ipaddr] = cDict.get(ipaddr, 0) + 1
  14. print cDict

步骤二:使用函数式编程实现

  1. [root@py01 bin]# vim countweb2.py
  2. !/usr/bin/env python
  3. import re
  4. def countPatt(patt, fname):   #定义可以在指定文件中搜索指定字符串的函数
  5. cDict = {}
  6. with open(fname) as f:
  7. for eachLine in f:
  8. m = re.search(patt, eachLine)
  9. if m is not None:
  10. k = m.group()
  11. cDict[k] = cDict.get(k, 0) + 1
  12. return cDict
  13. def test():
  14. logfile = '/var/log/httpd/access_log'
  15. patt_ip = '^\d+\.\d+\.\d+\.\d+'
  16. print countPatt(patt_ip, logfile)
  17. patt_br = 'Firefox|MSIE'
  18. print countPatt(patt_br, logfile)
  19. if __name__ == '__main__':
  20. test()

案例3:扫描存活主机

3.1 问题

编写扫描存活主机的脚本,主要要求如下:

  • 调用系统的ping命令进行扫描
  • 扫描教室环境下所有存活的主机
  • 采用多线程的方式编写
  • 方案

os模块的system()函数可以调用系统命令,其返回值是系统命令退出码,也就是如果系统命令成功执行,返回0,如果没有成功执行,返回非零值。

本例扫描主机,可以调用系统的ping命令,通过退出码来判断是否ping通了该主机。如果顺序执行,每个ping操作需要消耗数秒钟,全部的254个地址需要10分钟以上。而采用多线程,可以实现对这254个地址同时执行ping操作,并发的结果就是将执行时间缩短到了10秒钟左右。

3.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写脚本

  1. [root@py01 bin]# vim mtping.py
  2. #!/usr/bin/env python
  3. import subprocess
  4. import threading
  5. import sys
  6. def ping(ip):
  7. result = subprocess.call("ping -c2 %s &> /dev/null" % ip, shell=True)
  8. if result:
  9. print "%s:down" % ip
  10. else:
  11. print "%s:up" % ip
  12. if __name__ == '__main__':
  13. if len(sys.argv) != 2:
  14. print "Usage: %s subnet" % sys.argv[0]
  15. sys.exit(1)
  16. net_list = sys.argv[1].split('.')
  17. net = '.'.join(net_list[:-1])
  18. ips = ("%s.%s" % (net, i) for i in range(1, 255))
  19. for ip in ips:
  20. t = threading.Thread(target=ping, args=(ip,))
  21. t.start()

步骤二:测试脚本执行

  1. [root@py01 bin]# python mtping.py 172.40.51.0

脚本接受命令行参数,只要给定网段就可以实现对该网段中所有ip地址的ping操作。


案例4:利用多线程实现ssh并发访问

4.1 问题

编写ssh客户端脚本,主要要求如下:

  • 在文件中取出所有远程主机IP地址
  • 在shell命令行中接受远程服务器IP地址文件、远程服务器密码以及在远程主机上执行的命令
  • 通过多线程实现在所有的远程服务器上并发执行命令
  • 方案

python的paramiko模块可以实现ssh客户端的功能,使用起来也比较简单。但是当服务器非常多的时候,每台服务器上执行完全相同的简单操作,也会花费大量的时间。

通过ssh加上多线程,可以实现并发访问。为了将程序写的灵活性更强,把要执行的命令以位置参数的方式来提供。

4.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写脚本

  1. [root@py01 bin]# vim remote_comm.py
  2. #!/usr/bin/env python
  3. import paramiko
  4. import os
  5. import sys
  6. import threading
  7. def remote_comm(host, password, comm):
  8. ssh = paramiko.SSHClient()
  9. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  10. ssh.connect(host, username='root', password=password)
  11. stdin, stdout, stderr = ssh.exec_command(comm)
  12. out = stdout.read()
  13. err = stderr.read()
  14. if out:
  15. print "[%s:out]: %s" % (host, out),
  16. if err:
  17. print "%s:Error: %s", (host, err),
  18. ssh.close()
  19. if __name__ == '__main__':
  20. if len(sys.argv) != 4:
  21. print "Usage: %s ipfile password 'comm'" % sys.argv[0]
  22. sys.exit(1)
  23. ipfile = sys.argv[1]
  24. if not os.path.isfile(ipfile):
  25. print "No such file: %s" % ipfile
  26. sys.exit(2)
  27. password = sys.argv[2]
  28. comm = sys.argv[3]
  29. with open(ipfile) as fobj:
  30. for line in fobj:
  31. ip = line.strip()
  32. t = threading.Thread(target=remote_comm, args=(ip, password, comm))
  33. t.start()

步骤二:测试脚本执行

  1. [root@py01 bin]# python remote_comm.py ipaddr.txt tedu.cn 'useradd bob'

脚本接受命令行参数,其中ipaddr.txt是存放所有远程主机ip地址的文件,文件中每个ip地址占一行。tedu.cn是远程主机的密码(所有远程主机密码需要是一致的)。最后的命令需要写在引号中。

该示例执行成功后,会在所有远程主机上创建一个名为bob的用户。

Prthon多线程和模块的更多相关文章

  1. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

    由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...

  2. 网络编程 多线程/socketserver模块/ threading.local

    线程:进程中负责程序执行的执行单元. 多线程:在1个进程中存在多个线程. 进程只是用来把资源集中在一起,而线程才是cpu上的执行单位. 每个进程都会默认有一个控制线程也叫作主线程. 进程之间是竞争关系 ...

  3. 再看python多线程------threading模块

    现在把关于多线程的能想到的需要注意的点记录一下: 关于threading模块: 1.关于 传参问题 如果调用的子线程函数需要传参,要在参数后面加一个“,”否则会抛参数异常的错误. 如下: for i ...

  4. day 30 多线程 socketserver模块补充

    内容回顾: socket 模块 服务端:收发数据 - > accept/recv 客户端:收发数据 -> connect/recv 1. 考试题 1. 解释性和编译型 编译型: 先把代码编 ...

  5. 多线程threading模块

    python的多线程编程 简介 多线程编程技术可以实现代码并行性,优化处理能力,同时功能的更小划分可以使代码的可重用性更好.Python中threading和Queue模块可以用来实现多线程编程. 详 ...

  6. Python:多线程threading模块

    目录 Thread对象 Lock对象 local对象 Thread对象: 多任务可以由多进程完成,也可以由一个进程内的多线程完成.进程是由至少1个线程组成的. threading模块在较低级的模块 _ ...

  7. python编程中的并发------多线程threading模块

    任务例子:喝水.吃饭动作需要耗时1S 单任务:(耗时20s) for i in range(10): print('a正在喝水') time.sleep(1) print('a正在吃饭') time. ...

  8. Python_多线程threading模块

    python 在执行的时候会淡定的在CPU上只允许一个线程运行,故Python在多核CPU的情况下也只能发挥出单核的功能,其中的原因:gil锁 gil 锁 (全局解释器锁):每个线程在执行时都需要先获 ...

  9. Python(多线程threading模块)

    day27 参考:http://www.cnblogs.com/yuanchenqi/articles/5733873.html CPU像一本书,你不阅读的时候,你室友马上阅读,你准备阅读的时候,你室 ...

随机推荐

  1. R时间序列分析实例

    一.作业要求 自选时间序列完成时间序列的建模过程,要求序列的长度>=100. 报告要求以下几部分内容: 数据的描述:数据来源.期间.数据的定义.数据长度. 作时间序列图并进行简单评价. 进行时间 ...

  2. redis作为消息队列的原理

    Redis队列功能介绍 List 转:https://blog.csdn.net/cestlavieqiang/article/details/84197736 常用命令: Blpop删除,并获得该列 ...

  3. Redis 服务端程序实现原理

    上篇我们简单介绍了 redis 客户端的一些基本概念,包括其 client 数据结构中对应的相关字段的含义,本篇我们结合这些,来分析分析 redis 服务端程序是如何运行的.一条命令请求的完成,客户端 ...

  4. oracle中pl/sql 练习题----输入部门编号,在控制台打印这个部门的名称,总人数,平均工资(基本工资+奖金)

    一. 思路:声明record类型的变量,根据 多表联合查询查出想要的数据,最后输出. 二.注意:record类型不一定只是一个表中的数据,也可以声明不同表中的数据类型. 三.语句如下: declare ...

  5. iOS/macOS推荐个高效苹果开发工具, JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,支持Swift/Objective-C,极速转换

    CCJSON 是一款运行在macOS上 JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,可识别嵌套模型,字典/数组,支持Swift/Objective-C,操作方便,极速转换.下载 效果 ...

  6. 全文搜索技术--solr7.1之mysql的安装步骤

    1.安装命令 #>在线安装wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 输完上面一句话不能正常的下载安装 ...

  7. 【WebGL】WebGL API 详解

    基于 WebGL Specifications 最全面的API释疑. 类型以及对象定义 这部分内容主要定义一部分类型和数据结构. typedef unsigned long GLenum; typed ...

  8. 【5min+】更好的选项实践。.Net Core中的IOptions

    系列介绍 [五分钟的dotnet]是一个利用您的碎片化时间来学习和丰富.net知识的博文系列.它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net ...

  9. django自动生成接口文档

    我们在实际项目中,会需要将我们的一些接口的信息返回给前端,便于前后端的交互,在实际使用中,这种自动生成接口文档的模块很多,我主要是用REST framework自动生成接口文档,这个需要用到的是cor ...

  10. 解决WSL在执行32位程序时报错“Exec format error”的问题

    当你尝试在WSL上运行32位的程序时,shell将会报错:cannot execute binary file: Exec format error. 这是因为WSL目前暂不支持32位的ELF可执行文 ...