Python Day9
Paramiko模块
paramiko模块基于SSH用于连接远程服务器并执行相关操作
- 基于用户名密码连接:
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='shaolin', password='123')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()
- 基于公钥密钥连接:
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') #密钥位置
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='shaolin', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()
SFTPClient
用于连接远程服务器并执行上传下载
- 基于用户名密码上传下载
import paramiko
transport = paramiko.Transport(('hostname',22))
transport.connect(username='shaolin',password='123')
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
- 基于公钥密钥上传下载
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='shaolin', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
threading模块
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不独立拥有系统资源,但它可与同属一个进程的其它线程共享该进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个应用程序都至少有一个进程和一个线程。线程是程序中一个单一的顺序控制流程。在单个程序中同时运行多个线程完成不同的被划分成一块一块的工作,称为多线程。
线程有2种调用方式,如下:
- 直接调用
import threading
import time
def sayhi(num): #定义每个线程要运行的函数
print("running on number:%s" %num)
time.sleep(3)
if __name__ == '__main__':
t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
t1.start() #启动线程
t2.start() #启动另一个线程
print(t1.getName()) #获取线程名
print(t2.getName())
- 继承式调用
import threading
import time
class MyThread(threading.Thread):
def __init__(self,num):
super(MyThread,self).__init__()
self.num = num
def run(self):#定义每个线程要运行的函数
print("running on number:%s" %self.num)
time.sleep(3)
if __name__ == '__main__':
t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()
下面是Thread类的主要方法:
- start 线程准备就绪,等待CPU调度
- setName 为线程设置名称
- getName 获取线程名称
- setDaemon 设置为后台线程或前台线程(默认是False,前台线程)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止。如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止。 - join 该方法非常重要。它的存在是告诉主线程,必须在这个位置等待子线程执行完毕后,才继续进行主线程的后面的代码。但是当setDaemon为True时,join方法是无效的。
- run 线程被cpu调度后自动执行线程对象的run方法
Join & Daemon
- Join等待线程执行完毕
import threading
import time
def run(n):
print("task ",n )
time.sleep(2)
print("task done",n)
start_time = time.time()
t_objs = [] #存线程实例
for i in range(50):
t = threading.Thread(target=run,args=("t-%s" %i ,))
t.start()
t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里
for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
t.join()
print("----------all threads has finished...")
print("cost:",time.time() - start_time)
- Daemon 守护线程,主线程执行完毕,不管守护线程是否执行完毕都结束
import threading
import time
def run(n):
print("task ",n )
time.sleep(2)
print("task done",n,threading.current_thread())
start_time = time.time()
for i in range(50):
t = threading.Thread(target=run,args=("t-%s" %i ,))
t.setDaemon(True) #把当前线程设置为守护线程
t.start()
time.sleep(2)
print("----------all threads has finished...",threading.current_thread(),threading.active_count())
print("cost:",time.time() - start_time)
线程锁(互斥锁Mutex)
- Lock 普通锁(不可嵌套)
- RLock 普通锁(可嵌套)常用
- Semaphore 信号量
- event 事件
- condition 条件
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?
import time
import threading
def addNum():
global num #在每个线程中都获取这个全局变量
print('--get num:',num )
time.sleep(1)
num -=1 #对此公共变量进行-1操作
num = 100 #设定一个共享变量
thread_list = []
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
t.join()
print('final num:', num )
正常来讲,这个num结果应该是0, 但在python 2.7上多运行几次,会发现,最后打印出来的num结果不总是0,为什么每次运行的结果不一样呢? 哈,很简单,假设你有A,B两个线程,此时都 要对num 进行减1操作, 由于2个线程是并发同时运行的,所以2个线程很有可能同时拿走了num=100这个初始变量交给cpu去运算,当A线程去处完的结果是99,但此时B线程运算完的结果也是99,两个线程同时CPU运算的结果再赋值给num变量后,结果就都是99。那怎么办呢? 很简单,每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁, 这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。
*注:不要在3.x上运行,不知为什么,3.x上的结果总是正确的,可能是自动加了锁
- 加锁版本
import time
import threading
def addNum():
global num #在每个线程中都获取这个全局变量
print('--get num:',num )
time.sleep(1)
lock.acquire() #修改数据前加锁
num -=1 #对此公共变量进行-1操作
lock.release() #修改后释放
num = 100 #设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
t.join()
print('final num:', num )
GIL VS Lock
Python已经有一个GIL来保证同一时间只能有一个线程来执行了,为什么这里还需要lock? 注意啦,这里的lock是用户级的lock,跟那个GIL没关系 ,具体我们通过下图来看一下+配合我现场讲给大家,就明白了。
RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
import threading,time
def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2)
if __name__ == '__main__':
num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1:
print(threading.active_count()) #打印当前有多少个线程
else:
print('----all threads done---')
print(num,num2)
Semaphore(信号量)
- 类名:BoundedSemaphore
- 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time
def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s\n" %n)
semaphore.release()
if __name__ == '__main__':
semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run,args=(i,))
t.start()
while threading.active_count() != 1:
pass #print threading.active_count()
else:
print('----all threads done---')
Events
- 类名:Event
- 事件主要提供了三个方法 set、wait、clear。
- 事件机制:全局定义了一个“Flag”,如果“Flag”的值为False,那么当程序执行wait方法时就会阻塞,如果“Flag”值为True,那么wait方法时便不再阻塞。这种锁,类似交通红绿灯(默认是红灯),它属于在红灯的时候一次性阻挡所有线程,在绿灯的时候,一次性放行所有的排队中的线程。
- clear:将“Flag”设置为False
- set:将“Flag”设置为True
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
import time
import threading
event = threading.Event()
def lighter():
count = 0
event.set() #先设置绿灯
while True:
if count >5 and count < 10: #改成红灯
event.clear() #把标志位清了
print("\033[41;1mred light is on....\033[0m")
elif count >10:
event.set() #变绿灯
count = 0
else:
print("\033[42;1mgreen light is on....\033[0m")
time.sleep(1)
count +=1
def car(name):
while True:
if event.is_set(): #代表绿灯
print("[%s] running..."% name )
time.sleep(1)
else:
print("[%s] sees red light , waiting...." %name)
event.wait()
print("\033[34;1m[%s] green light is on, start going...\033[0m" %name)
light = threading.Thread(target=lighter,)
light.start()
car1 = threading.Thread(target=car,args=("Tesla",))
car1.start()
queue队列
class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out (后进先出)
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列
class queue.deque :双向队列
- Queue.qsize() #查看队列大小
- Queue.empty() #return True if empty 返回True则表示队列为空
- Queue.full() # return True if full 判断当前队列是否已满,返回True或者False
- Queue.put(item, block=True, timeout=None) #添加
- Queue.get(block=True, timeout=None) #拿出
- Queue.get_nowait() #没有队列则会报错不会卡住
———————————————————————————————————————————————————
qsize() 获取当前队列中元素的个数,也就是队列的大小
empty() 判断当前队列是否为空,返回True或者False
full() 判断当前队列是否已满,返回True或者False
put(self, block=True, timeout=None)
往队列里放一个元素,默认是阻塞和无时间限制的。如果,block设置为False,则不阻塞,这时,如果队列是满的,放不进去,就会弹出异常。如果timeout设置为n秒,则会等待这个秒数后才put,如果put不进去则弹出异常。get(self, block=True, timeout=None)
从队列里获取一个元素。参数和put是一样的意思。join() 阻塞进程,直到所有任务完成,需要配合另一个方法task_done。
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
下面来学习一个最基本的生产者消费者模型的例子
import threading,time
import queue
q = queue.Queue(maxsize=10)
def Producer(name):
count = 1
while True:
q.put("骨头%s" % count)
print("生产了骨头",count)
count +=1
time.sleep(0.1)
def Consumer(name):
while True:
print("[%s] 取到[%s] 并且吃了它..." %(name, q.get()))
time.sleep(1)
p = threading.Thread(target=Producer,args=("张三",))
c = threading.Thread(target=Consumer,args=("李四",))
c1 = threading.Thread(target=Consumer,args=("旺财",))
p.start()
c.start()
c1.start()
Python Day9的更多相关文章
- Python day9函数部分
函数的学习:函数对于一门编程语言来说挺重要的,尤其是c语言,是完全使用函数来编写的 1.函数的定义:逻辑结构化和过程化的一种编程方法 def squre(x): "求一个数的平方 retur ...
- python—day9 函数的定义、操作使用方法、函数的分类、函数的嵌套调用
一.函数的定义 函数的四个组成部分: 函数名. 函数体. 函数返回值. 函数参数 1.概念:重复利用的工具,可以完成特定功能的代码块,函数是存放代码块的容器 2.定义: def:声明函数的关键词 函数 ...
- python基础 Day9
python Day9 函数的初识 #代码的可读性较好 s=[1,2,3,4,5,5] def list_len(S): count=0 for i in s: count+=1 print(coun ...
- python基础-迭代器和生成器
一.递归和迭代 1.递归:(问路示例) 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 2.迭代:简单理 ...
- 20 Python 常用模块
collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict. ...
- Python面向对象 杂篇(后记)
异常处理 什么是异常: 我们在调试程序时,常常会因为各种报错信息导致程序无法运行,异常也是一个对象,用来表示错误.我们可以捕捉异常,并做相应处理,从而增加代码的友好程度. 异常处理: ...
- Day9 - Python 多线程、进程
Python之路,Day9, 进程.线程.协程篇 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...
- python学习day9
目录 一.队列 二.生产者消费者模型 三.协程 四.select\poll\epoll 五.paramiko 六.mysql API调用 一.队列(queue) 队列分以下三种: class queu ...
- Python之路,Day9, 进程、线程、协程篇
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
随机推荐
- Linux监控工具介绍系列——free
在Linux系统中,我们查看.监控系统内存使用情况,一般最常用的命令就是free.free命令其实非常简单,参数也非常简单,但是里面很多知识点未必你都掌握了.下面总结一下我所了解的free命令.如有不 ...
- IE8 ajax缓存问题
娘希匹,又遇到缓存问题了. 下面的代码,在其他浏览器都是正常的,但是在IE8中出现诡异问题. $.ajax({ url:dataUrl, data:encodeURI(currentjsonform) ...
- Windows下Apache + PHP SESSION丢失的惨痛经历
今天的工作是迁移一个PHP站点至新服务器. 创建一台Windows Server 2008虚拟机,并在其上停掉net stop http服务(避免争抢80端口),安装配置 Apache + PHP,迁 ...
- 【Linux】解决Wesnoth中文乱码问题
现在使用的系统是Linux Mint 18,安装了Wesnoth,发现打开之后部分中文显示正常,部分中文显示为乱码. 谷歌出的很多办法都只给出了几条指令,但并不具有普适性,我提供一种新的方法,通过修改 ...
- logback配置详解2<appender>
logback 常用配置详解(二) <appender> <appender>: <appender>是<configuration>的子节点,是负责写 ...
- 复制粘贴出来的悲剧----spring实现文件下载和HttpStatus.CREATED
今天真是被自己的懒惰和复制粘贴给坑惨了... 网上有这么一个spring下载文件的最佳实践: @RequestMapping("download") public Response ...
- FeWeb基础之JavaScript简介
FeWeb基础之JavaScript简介 1.JavaScript的基本介绍 JavaScript是一种基于对象和事件驱动并具有安全性能的脚本语言,它是通过嵌入或调入在标准的HTML语言中实现的.Ja ...
- spring mvc 快速入门
---------- 转自尚学堂 高淇 --------- Spring MVC 背景介绍 Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块.使用 Spring 可插入的 MVC ...
- 学习大神笔记之 “MyBatis学习总结(一)”
1.准备工作 软件:eclipse. mysql .navicat for mysql 包:mybatis-3.1.1.jar mysql-connector-java-5.1.7-bin.jar ...
- 三维网格补洞算法(Poisson Method)
下面介绍一种基于Poisson方程的三角网格补洞方法.该算法首先需要根据孔洞边界生成一个初始化补洞网格,然后通过法向估算和Poisson方程来修正补洞网格中三角面片的几何形状,使其能够适应并与周围的原 ...