Python教程

第10章 Python 多线程技术简述 - Selenium2 自动化测试

本文主要是介绍第10章 Python 多线程技术简述 - Selenium2 自动化测试,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在学完第9章Selenium Grid之后,我们了解到Selenium Grid虽然可以分布式执行测试用例,但它并不支持并行。“分布式”和“并行”是两个完全不同的概念,分布式只负责将一个测试用例远程调用到不同的环境下执行;而并行强调“同时”执行多个任务。如何实现并行呢?可以利用编程语言提供的多线程(或多进程)技术来实现并行。
本章将学习Python的多线程与多进程技术,并将其应用到自动化测试用例的执行中。
在使用多线程之前,我们首先要理解进程和线程的概念。

什么是进程?
计算机程序只不过是磁盘中可执行的二进制(或其他类型)数据。它们只有在被读取到内存中、被操作系统调用的时候才开始它们的生命周期。进程是程序的一次执行,每个进程都有自己的地址空间、内存、数据栈,以及其他记录其运行轨迹的辅助数据。操作系统管理在其上面运行的所有进程,并为这些进程公平地分配时间。
什么是线程?
线程(有时被称为轻量级进程)与进程有些相似,不同的是,所有的线程都运行在同一个进程中,共享相同的运行环境。我们可以想象成是在主进程或“主线程”中并行运行的“迷你进程”。

10.1 单线程的时代

在单线程时代,当处理器需要处理多个任务时,必须对这些任务安排执行顺序,并按照这个顺序来执行任务。假如我们创建了两个任务;听音乐(music)和看电影(movie),在单线程中,我们只能按先后顺序来执行这两个任务。下面就通过一个例子来演示。

onethread.py

from time import sleep, ctime


# 听音乐任务
def music():
    print('I was listening to music! %s' % ctime())
    sleep(2)


# 看电影任务
def movie():
    print('I was at the movies! %s' % ctime())
    sleep(5)


if __name__ == '__main__':
    music()
    movie()
    print('all end:', ctime())

分别创建了两个任务music和movie,执行时间分别为2秒和5秒,通过sleep()方法设置休眠时间来模拟任务的运行时间。
运行结果。

D:\Python38\python.exe F:/python_project/学习验证/onethread.py
I was listening to music! Mon Sep 20 14:53:17 2021
I was at the movies! Mon Sep 20 14:53:19 2021
all end: Mon Sep 20 14:53:24 2021

Process finished with exit code 0

从运行结果可看到,程序从11分04秒开始播放music,11分06秒结束并开始movie的播放,最后,到11分11秒movie播放结束,总耗时7秒。
现在。我们对上面的例子做些调整,使它看起来更加有意思。
首先music和movie作为播放器,在用户使用时,可以根据用户的需求来播放任意的歌曲和影片,并且我们希望播放器能够提供循环播放的功能,尤其对于音乐播放器来说这个很重要,改造后的程序如下。

onethread2.py

from time import sleep, ctime


# 音乐播放器
def music(func, loop):
    for i in range(loop):
        print('I was listening to %s! %s' % (func, ctime()))
        sleep(2)


# 视频播放器
def movie(func, loop):
    for i in range(loop):
        print('I was at the %s! %s' % (func, ctime()))
        sleep(5)


if __name__ == '__main__':
    music('爱情买卖', 2)
    movie('阿凡达', 2)
    print('all end:', ctime())

给music()和movie()两个函数设置参数:播放文件和播放次数。而函数中通过for循环控制播放的次数。再次运行,结果如下。

D:\Python38\python.exe F:/python_project/学习验证/onethread2.py
I was listening to 爱情买卖! Mon Sep 20 14:56:34 2021
I was listening to 爱情买卖! Mon Sep 20 14:56:36 2021
I was at the 阿凡达! Mon Sep 20 14:56:38 2021
I was at the 阿凡达! Mon Sep 20 14:56:43 2021
all end: Mon Sep 20 14:56:48 2021

Process finished with exit code 0

从运行结果可以看到,程序从42分36秒开始播放music,42分40秒music两轮播放结束并开始播放movie;42分50秒两个任务结束,最终总耗时14秒。

10.2 多线程技术

Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。threading基于Java的线程模型设计。锁(Lock)和条件变量(Condition)在Java中是对象的基本行为(每一个对象都自带了锁和条件变量),而在Python中则是独立的对象。

10.2.1 threading模块

我们应该避免使用thread模块,原因是它不支持守护线程。当主线程退出时,所有的子线程不管它们是否还在工作,都会被强行退出。有时我们并不希望发生这种行为,这时就引入了守护线程的概念。threading模块支持守护线程,所以,我们直接使用threading来改进上面的例子。
threads.py

from time import sleep, ctime
import threading

# 音乐播放器
def music(func, loop):
    for i in range(loop):
        print("I was listening to %s! %s" % (func, ctime()))
        sleep(2)


# 视频播放器
def movie(func, loop):
    for i in range(loop):
        print("I was at the %s! %s" % (func, ctime()))
        sleep(5)

# 创建线程数组
threads = []

# 创建线程t1,并添加到线程数组
t1 = threading.Thread(target=music, args=('爱情买卖',2))
threads.append(t1)

# 创建线程t2,并添加到线程数组
t2 = threading.Thread(target=movie, args=('阿凡达', 2))
threads.append(t2)

if __name__ == '__main__':
    # 启动线程
    for t in threads:
        t.start()
    # 守护线程
    for t in threads:
        t.join()
    print('all end: %s' % ctime())

通过for循环遍历threads数组中所装载的线程;start()开始线程活动,join()等待线程终止。如果不使用join()方法对每个线程做等待终止,那么在线程运行的过程中可能会去执行最后的打印“all end:..”。

class threading.Thread()方法说明:

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is t he callable obj ect t o be invoked by t he run() m ethod. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.
args is the argument tuple for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.

运行结果。

D:\Python38\python.exe F:/python_project/学习验证/threads.py
I was listening to 爱情买卖! Mon Sep 20 14:28:52 2021
I was at the 阿凡达! Mon Sep 20 14:28:52 2021
I was listening to 爱情买卖! Mon Sep 20 14:28:54 2021
I was at the 阿凡达! Mon Sep 20 14:28:57 2021
all end: Mon Sep 20 14:29:02 2021

Process finished with exit code 0

从上面的运行结果可以看出,两个子线程(music、movie)同时启动于11分24秒,直到所有线程结束于11分34秒,总耗时10秒。movie的两次电影循环共需要10秒,music的歌曲循环需要4秒,从执行结果可以看出两个线程达到了并行工作。

 

这篇关于第10章 Python 多线程技术简述 - Selenium2 自动化测试的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!