• 【python自动化第九篇:进程,线程,协程】


    简要:

    1. paramiko模块
    2. 进程与线程
    3. python GIL全局解释器锁

    一、PARAMIKO模块

    • 实现远程ssh执行命令
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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()                                           #关闭连接
    
    • 远程传输文件 
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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链接远程机执行命令 
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    import paramiko
    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收发文件
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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必须要先创建一个线程;
    • 进程和线程的区别:
      • 线程共享内存空间,进程是独立的内存空间;
      • 同一个进程的线程之间可以直接互相访问,连个进程要想通信,必须要经过一个中间代理来实现;
      • 新的线程容易创建,新的进程需要克隆他的父进程;
      • 一个线程可以控制和操作同一进程里的其他线程;
      • 对于主线程的修改会影响到其他线程的运行(数据共享);对于一个父进程的修改,不会影响子进程(数据不共享)
    • 简单的多线程栗子:

        一般模式:

    #!/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')
    

          函数形式:

    #!/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)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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()) 当前线程,线程个数 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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)
    

        守护线程:非守护线程退出了,也就退出了,二守护线程也就不再那么重要了,

             守护进程就是要守护者其他进程,主线程没法被设置成守护线程的

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    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):也就是互斥锁

    #!/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 -*-
    #Author:wanghui
    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)
    View Code

        信号量:互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    import threading,time
    def run(n):
        semaphore.acquire()       #获取信号量
        time.sleep(1)
        print("run the thread:%s
    " %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)
    View Code

     三、事件(Event)

    python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

    以下是个红绿灯的例子:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author:wanghui
    import threading,time
    event = threading.Event()
    
    def lighter():
        count = 0       #设置状态位
        event.set()     #设置为通行状态,也就是绿灯
        while True:
            if count > 3 and count < 6:
                event.clear()            #这会儿变成红灯
                print('33[41;1mred light is on...33[0m')
            elif count > 6:
                event.set()        #变成绿灯
                count=0            #标志位清空
            else:
                print('33[42;1mgreen lignt is on33[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()
    

      

  • 相关阅读:
    03_HibernateSessionFactory源码分析
    02_ThreadLocal语法与源码分析
    01_Java 软、弱引用语法介绍
    Xpath定位和CssSelector定位的区别
    Mac 上自动化构建 jenkins 操作步骤(中)git环境搭建
    Mac 上自动化构建 jenkins 操作步骤(上)
    UI自动化常用的几种等待方法
    Selenium-webdriver 之元素定位方法归类
    统一初始化(Uniform Initialization)
    Mac下electron编译
  • 原文地址:https://www.cnblogs.com/wanghui1991/p/5883724.html
Copyright © 2020-2023  润新知