【python自动化第九篇:进程,线程,协程】
简要:
- paramiko模块
- 进程与线程
- python GIL全局解释器锁
一、PARAMIKO模块
- 实现远程ssh执行命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko ssh = paramiko.SSHClient() #创建ssh对象 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #允许连接不在know_hosts文件中的主机 ssh.connect(hostname = '192.168.1.102' ,port = 22 ,username = 'wanghui' ,password = '123456' ) #开始连接服务器 stdin,stdout,stderr = ssh.exec_command( 'df' ) #执行命令 #resault = stdout.read() #收集命令执行结果 #print(resault.decode()) #三元运算实现 res,err = stdout.read(),stderr.read() resault = res if res else err print (resault.decode()) ssh.close() #关闭连接 |
- 远程传输文件
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko transport = paramiko.Transport(( '10.70.18.2' , 22 )) #创建传输对象 transport.connect(username = 'root' ,password = 'abc/123' ) #登录认证 sftp = paramiko.SFTPClient.from_transport(transport) #创建sftp对象 sftp.put( 'test' , '/opt/ssh_transe.txt' ) #上传文件到/opt下,存放名称改为ssh_transe.py sftp.get( '/opt/ssh_transe.txt' , 'test2' ) #下在文件到当前目录下并改名为test2 transport.close() #关闭连接 |
- 使用密钥ssh链接远程机执行命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko<br> private_key = paramiko.RSAKey.from_private_key_file( 'id_rsa' ) #创建私钥对象,指定私钥文件 ssh = paramiko.SSHClient() #实例化ssh ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #自动添加到对方的know_hosts文件 ssh.connect(hostname = '10.70.18.2' ,port = 22 ,username = 'root' ,pkey = private_key) #使用私钥链接机器 stdin,stdout,stderr = ssh.exec_command( 'ls /opt' ) #执行第一条命令 resault = stdout.read() print (resault.decode()) stdin,stdout,stderr = ssh.exec_command( 'df' ) #执行第二条命令 resault1 = stdout.read() print (resault1.decode()) ssh.close() |
- 使用密钥sftp收发文件
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko private_key = paramiko.RSAKey.from_private_key_file( 'id_rsa' ) #创建私钥对象,指定私钥文件 transport = paramiko.Transport(( '10.70.18.2' , 22 )) #创建传输对象 transport.connect(username = 'root' ,pkey = private_key) #指定用户和私钥连接 sftp = paramiko.SFTPClient.from_transport(transport) #创建sftp实例 #sftp.put('test2','/opt/ssss') #上传文件 sftp.get( '/opt/ssss' , 'message.txt' ) #下载文件 |
二、进程&线程
- 线程:
- 操作系统能够尽心运算调度的最小单位,他被包含在进程当中,是进程中的实际运作单位;
- 一条线程指的是进程中的单一顺序的控制流,一个进程可以并发多个线程,每个进程并行执行多个线程;
- 线程就是cpu执行时所需要的一段执行的上下文;
- 子线程又可以创建子线程;
- 启动线程的速度要大于进程
- 进程:
- 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用、内存的管理、网络接口的调用等;
- 对各种资源管理的集合就可以成为进程;
- 进程要操作cpu必须要先创建一个线程;
- 进程和线程的区别:
- 线程共享内存空间,进程是独立的内存空间;
- 同一个进程的线程之间可以直接互相访问,连个进程要想通信,必须要经过一个中间代理来实现;
- 新的线程容易创建,新的进程需要克隆他的父进程;
- 一个线程可以控制和操作同一进程里的其他线程;
- 对于主线程的修改会影响到其他线程的运行(数据共享);对于一个父进程的修改,不会影响子进程(数据不共享)
- 简单的多线程栗子:
一般模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time def run(n): print ( 'task ' ,n) time.sleep( 2 ) #多线程执行:并行执行 t1 = threading.Thread(target = run,args = ( 't1' ,)) #定义线程 t1.start() #启动线程 t2 = threading.Thread(target = run,args = ( 't2' ,)) t2.start() #单线程执行: run( 't1' ) #直接运行函数 run( 't2' ) |
函数形式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time class Mythread(threading.Thread): #继承threading.Thread def __init__( self ,n): #初始化 super (Mythread, self ).__init__() #重构 self .n = n #实例化参数n def run( self ): #定义run函数 print ( 'running task' , self .n) t1 = Mythread( 't1' ) t2 = Mythread( 't2' ) t1.start() t2.start() |
多线程执行时间讨论(join)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time def run(n): #定义函数 print ( 'running task' ,n) time.sleep( 2 ) print ( 'task down' ,n) start_time = time.time() #定义开始时间 t_objs = [] #存线程实例 for i in range ( 50 ): #定义50个并发执行的线程 t = threading.Thread(target = run,args = ( 'thread:%s' % i,)) #实例化线程 t.start() #启动线程 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 for t in t_objs: #循环线程实例,等待所有线程执行完毕 t.join() cost_time = time.time() - start_time #定义结束时间 print ( "cost time " ,cost_time) |
还有俩关于线程的参数:threading.current_thread(),threading.active_count()) 当前线程,线程个数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time def run(n): #定义函数 print ( 'running task' ,n) time.sleep( 2 ) print ( 'task down' ,n) start_time = time.time() #定义开始时间 t_objs = [] #存线程实例 for i in range ( 50 ): #定义50个并发执行的线程 t = threading.Thread(target = run,args = ( 'thread:%s' % i,)) #实例化线程 t.start() #启动线程 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 # for t in t_objs: #循环线程实例,等待所有线程执行完毕 # t.join() cost_time = time.time() - start_time #定义结束时间 print ( "all threads has finished..." ,threading.current_thread(),threading.active_count()) #打印当前线程,线程个数 print ( "cost time " ,cost_time) |
守护线程:非守护线程退出了,也就退出了,二守护线程也就不再那么重要了,
守护进程就是要守护者其他进程,主线程没法被设置成守护线程的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time def run(n): #定义函数 print ( 'running task' ,n) time.sleep( 2 ) print ( 'task down' ,n) start_time = time.time() #定义开始时间 t_objs = [] #存线程实例 for i in range ( 50 ): #定义50个并发执行的线程 t = threading.Thread(target = run,args = ( 'thread:%s' % i,)) #实例化线程 t.setDaemon( True ) # 设置当前线程设置为守护线程,一定要在start之前 t.start() #启动线程 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 cost_time = time.time() - start_time #定义结束时间 print ( "all threads has finished..." ,threading.current_thread(),threading.active_count()) #打印当前线程,线程个数 print ( "cost time " ,cost_time) |
全局解释器锁GIL:python的线程是调用操作系统原生的线程,python要调用C语言线程的时候,要注意到上下文的切换关系
(在python中同一时间,执行的线程只有一个,而不像是所谓的多核多处理那样)
线程锁(Mutex):也就是互斥锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time def run(n): #定义函数 lock.acquire() #获取一把锁 global num num + = 1 time.sleep( 1 ) #这话时候锁没有释放,需要等待释放才能接受下一个线程 lock.release() #释放锁 lock = threading.Lock() #定义锁实例 num = 0 #定义全局变量 t_objs = [] #存线程实例 for i in range ( 50 ): #定义50个并发执行的线程 t = threading.Thread(target = run,args = ( 'thread:%s' % i,)) #实例化线程 t.start() #启动线程 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 for t in t_objs: #循环线程实例,等待所有线程执行完毕 t.join() print ( "all threads has finished..." ) print ( 'num:' ,num) |
递归锁RLock问题:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
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,然后执行run1,run2.最后释放
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res, res2)
num, num2 = 0, 0 #定义变量
lock = threading.RLock() #定义递归锁
for i in range(10):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1: #当前线程不等于1那就继续打印结果
print(threading.active_count())
else:
print('----all threads done---')
print(num, num2)
信号量:互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading,time
def run(n):
semaphore.acquire() #获取信号量
time.sleep(1)
print("run the thread:%s\n" %n)
semaphore.release() #释放信号量
num = 0 #定义全局变量
semaphore = threading.BoundedSemaphore(5) #实例化信号量,最多允许5个线程并行
for i in range(40):
t = threading.Thread(target=run,args=(i,)) #并行40个线程
t.start() #启动线程
while threading.active_count() != 1:
print(threading.active_count())
else:
print("all threads done...")
print(num)
三、事件(Event)
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
以下是个红绿灯的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading,time event = threading.Event() def lighter(): count = 0 #设置状态位 event. set () #设置为通行状态,也就是绿灯 while True : if count > 3 and count < 6 : event.clear() #这会儿变成红灯 print ( '\033[41;1mred light is on...\033[0m' ) elif count > 6 : event. set () #变成绿灯 count = 0 #标志位清空 else : print ( '\033[42;1mgreen lignt 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 now red light is on ,stop" ) event.wait() print ( 'green light is on ,go %s!!' % name) car1 = threading.Thread(target = car,args = ( 'Moto' ,)) car1.start() light = threading.Thread(target = lighter,) light.start() |