python + uiautomator2编译平板语言工具并切换打包exe可执行文件1.1.4版本--终版(下)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: python + uiautomator2编译平板语言工具并切换打包exe可执行文件1.1.4版本--终版(下)

编写一个错误自动记录log的装饰器

只要在需要记录log的方法前加上:@errorlog 就可以了

def errorlog(func):
    logger = logging.getLogger()
    def wrapper(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)  # 执行传入的fn参数
        except Exception as e:
            logger.error(msg=e, exc_info=True)
    return wrapper

版本1.1.4源码

各个版本功能介绍:

操作步骤
双击devicesConnect.exe即可运行
使用此工具注意事项及操作步骤
1.电脑端cmd可执行adb命令,设备已预置安装所需apk文件。
2.myExcel文件夹中存放所需测试的Excel,文件名固定为Test.xlsx,并只能放一个。
3.Excel表中Select列不能为空,只能为0或1。
4.myExcel和resultExcel两个文件夹名字不能更改。
5.右布局的国家语言需要手动在excel表格中编辑格式。
语言切换工具1.1.4版本功能介绍:
1.优化语言切换判断
2.优化不存在语言判断
语言切换工具1.1.3版本功能介绍:
1.更新日志保存方式,修复控制台显示'GBK'编码报错问题。
2.优化运行出错的容错率,当前语言出错会跳过并保存日志。
3.控制台显示为空或乱码问题,请看pdf文档进行设置。
语言切换工具1.1.2版本功能介绍:
1.新增日志文件,可在resultExcel文件夹中查看
2.新增配置文件,在setting文件中,可更改对应元素位置(详细请看setting中的readme.txt)
3.新增语言判断,若当前语言不存在设备,则会跳过
4.新增warning信息对比,当设备无更新提示时会记录当前设备版本信息
语言切换工具1.1.1版本功能介绍:
1.可显示当前语言切换进度。
2.设备中无目标语言会跳过执行。
3.resultExcel文件夹中会生成测试结果,文件夹以当前时间命名。
4.生成的excel文件中会有对应截图超链接,需要点击两次才能跳转。

目录结构

image.png

readExcelFile.py

import xlrd
class RWExcel:
    def __init__(self,filename):
        # todo 打开excle
        self.xl = xlrd.open_workbook('{}'.format(filename))
        # todo 通过索引获取工作表
        self.table = self.xl.sheet_by_index(0)
        # print("工作表的名字为:{}".format(self.table.name))
        # 获取一共多少行
        self.rows = self.table.nrows
        # 获取一共有多少列
        self.cols = self.table.ncols
        # print("当前表一共有"+str(self.rows) +"行,"+ str(self.cols) + "列")
        # for i in range(rows):
        #     print(table.cell(i,0))   #打印第一列
    def getSelect(self):
        """
        :return: 获取表中select为1的行数(下标从0开始)
        """
        #读取表格第一列除去第一行的值
        self.fristcol = self.table.col_values(0)
        fristcol_list = []
        fristcol_list.append(self.table.cell(0,0).value) #把第一行第一列的值加进去
        for i  in range(1,len(self.fristcol)) :
            # 把除去第一行的第一列的0和1强转为int类型的数值,并且加入到列表里面(第一行的值最后也在,目的是为了后面通过下标找对应的行)
            fristcol_list.append(int(self.fristcol[i]))
        #print("当前表第一列的值为:{}".format(fristcol_list))
        #获取fristcol_list中为1的下标,同时用一个列表存储这些下标
        indexlist = []
        for  i in range(len(fristcol_list)) :
            if fristcol_list[i] == 1 :  #如果为1,那就是需要运行这一行的代码,此时获取下标,就相当于是获取第几行
                indexlist.append(i)  # i就是下标
        #print("当前表中select是1的行数为:{}".format(indexlist))
        return indexlist
    def selectLanguage(self):
        """
        :return: 获取表格中select为1所对应的语言列表
        """
        indexlist = self.getSelect()  #获取select为1的列
        #print("第二个方法里面的Select为1的行数{}".format(indexlist))
        #print("---------------------------------")
        languagelist = []
        for  i in  indexlist:
            #获取对应select为1的平台切换语言列表(第4列)
            language = self.table.cell(i,3).value
            languagelist.append(language)  #获取select为1对应的平板切换语言
        print("当前表中待切换语言:\n {}".format(languagelist))
        print("\n")
        return languagelist
    def list_dic(self):
        '''
        two lists merge a dict,a list as key,other list as value
        把select为1的行数作为键,把要切换的语言作为值
        :return:dict
        '''
        list1 = self.getSelect()
        list2 = self.selectLanguage()
        #把两个列表合并为一个字典,一个作为key,一个作为value
        dic = dict(map(lambda x, y: [x, y], list1, list2))
        return dic
    def differ(self,index):
        i = self.table.cell(index,2).value
        j = self.table.cell(index,4).value
        if i == j :
            print("匹配结果:一样")
            #print(i)
            #print("--------------------------------------")
            #print(j)
            return "PASS"
        if i != j :
            print("匹配结果:不一样")
            return "FAILED"

read SeriaNumber.py

import os
class adbDevices():
    def __init__(self):
        pass
    def readSN(self):
        '''
        :return:获取设备的sn号
        '''
        text = os.popen("adb devices | findstr /v List").read()
        Sn = text.split('d')[0].split()[0]
        return Sn

writeExcel.py

from openpyxl import load_workbook
from .readExcelFile import RWExcel
#写入已存在的xlsx文件
class Write_excel(object):
    '''修改excel数据'''
    def __init__(self,filename,index,msg):
        """
        :param filename: 测试的文件名
        :param index: 对应要写入的行数的下标
        :param msg: 需要写入的内容
        """
        self.filename = filename
        self.index = index
        self.msg = msg
    def write(self):
        #写入已存在的xlsx文件
        wb = load_workbook(self.filename)#生成一个已存在的wookbook对象
        wb1 = wb.active#激活sheet
        wb1.cell(self.index+1,5,self.msg)#往sheet中的第二行第五列写入msg的数据,注意这里的下标是从1开始
        wb.save(self.filename)  # 保存
    def write_result(self):
        result = RWExcel(self.filename).differ(self.index)
        # 写入已存在的xlsx文件
        wb = load_workbook(self.filename)  # 生成一个已存在的wookbook对象
        wb1 = wb.active  # 激活sheet
        wb1.cell(self.index + 1, 6, result)  # 把对比的结果写入到表格中
        wb.save(self.filename)  # 保存
        return result
    #图片超链接
    def write_hyperlink(self,path):
        result = "file:\\\\\{}".format(path)
        wb = load_workbook(self.filename)  # 生成一个已存在的wookbook对象
        wb1 = wb.active  # 激活sheet
        wb1.cell(self.index + 1, 7, result)  # 把截图的超链接写入到表格中
        wb.save(self.filename)  # 保存
        return result
    def saveExcel(self):
        pass

deviceConnect.py (主函数)

# coding=utf-8
import time
import datetime
from language_draft_exe03.commonFiles.readSerialNumber import adbDevices
from language_draft_exe03.commonFiles.readExcelFile import RWExcel
from language_draft_exe03.commonFiles.writeExcel import Write_excel
import uiautomator2 as u2
import os
import logging
import configparser
def errorlog(func):
    logger = logging.getLogger()
    def wrapper(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)  # 执行传入的fn参数
        except Exception as e:
            logger.error(msg=e, exc_info=True)
    return wrapper
class readWarningTest():
    def __init__(self):
        pass
    def copyExcel(self):
        """
        :return:返回复制后的excel的绝对路径
        """
        nowTime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
        self.makeFolder = os.popen(r"cd resultExcel && mkdir {} && cd {} && chdir".format(nowTime,nowTime)).read()
        self.makeFolderPath = self.makeFolder.strip()   #这个打印的鬼地址末尾有个\n , 这里把他去掉
        #print(self.makeFolderPath)
        self.rootdir = os.popen("copy .\myExcel\  {}\ /Y".format(self.makeFolderPath))
        self.resultExcelPath = "{}\Test.xlsx".format(self.makeFolderPath)
        print("--------------------表格备份完成----------------")
        #print(self.resultExcelPath,"-------------------------")
        return self.resultExcelPath
    def savelog(self):
        path =  "{}\main.log".format(self.makeFolderPath)
        logging.basicConfig(level=logging.DEBUG,  # 控制台打印的日志级别
                            filename=path,
                            filemode='w',  ##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
                            # a是追加模式,默认如果不写的话,就是追加模式
                            format=
                            '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                            # 日志格式
                            )
    def readConfig(self):
        self.cf = configparser.ConfigParser()
        self.cf.read("./setting/config.ini",encoding="utf-8-sig")  # 读取配置文件
    def getLanguageindex(self):
        self.readConfig()
        languageindex = self.cf.get("language&input", "languageindex") #获取[language&input]中languageindex对应的值
        return int(languageindex)-1
    def getUpdateindex(self):
        self.readConfig()
        Updateindex = self.cf.get("systemUpdate", "Updateindex") # 获取[systemUpdate]中Updateindex对应的值
        return int(Updateindex)
    def getExcelName(self):
        self.readConfig()
        excelName = self.cf.get("ExcelName",'excelName')
        return excelName
    def errorScreenshorts(self, msg, Changelanguage):
        self.d.screenshot("{}\{}_{}.jpg".format(self.makeFolderPath, Changelanguage, msg))
        self.picturePath = "{}\{}_{}.jpg".format(self.makeFolderPath, Changelanguage, msg)
    @errorlog
    def connect(self):
        self.savelog()
        logger = logging.getLogger()
        # 连接手机
        print("---------------正在获取设备的SN号----------------")
        logging.debug(msg="---------------正在获取设备的SN号----------------",exc_info=True)
        try:
            self.SN = adbDevices().readSN()  # 获取涉笔的SN号
            print("------------------获取成功,设备的SN号为:" + self.SN + "----------------------")
        except Exception as e:
            logger.error(e,exc_info=True)
            self.savelog()
        time.sleep(5)
        print("---------------------------正在连接设备---------------------")
        try:
            self.d = u2.connect(self.SN)  # HA12FYBL\HA12G0GW\HA169RPZ填入设备的SN号即可
        except Exception:
            logger.error('连接设备出错', exc_info=True)
        self.sizeTuple = self.d.window_size()
        print("--------------------设备连接成功,开始运行-----------------")
        self.savelog()
        #self.d.press('home')
        #print("回到主页面成功,正在把屏幕调到自然方向")
        #time.sleep(3)
        #self.d.set_orientation("n")  # or "natural"
        #print("屏幕调整完成,正在启动应用")
    @errorlog
    def readWarning(self,Changelanguage):
        """
        :param Changelanguage: 需要切换的语言
        :return: 返回切换语言之后的warningtext
        """
        self.savelog()
        logger = logging.getLogger()
        logger.debug('-------------------回到主界面成功,正在启动应用!-----------------', exc_info=True)
        self.d.press('home')
        time.sleep(3)
        self.d.implicitly_wait(20)
        #启动应用
        self.d.app_start("com.android.settings")
        logger.debug('---------------------应用启动成功---------------------', exc_info=True)
        #创建session连接对象,建议与设置应用的绑定连接
        s = self.d.session('com.android.settings',attach=True)
        time.sleep(3)
        #获取设备的尺寸
        #print(self.d.window_size())
        x = self.sizeTuple[0]
        y = self.sizeTuple[1]
        #print("屏幕的宽为:"+str(x) +",屏幕的高为:"+str(y)) #获取屏幕的宽高
        #1.进入设置之后,划动屏幕找到System
        time.sleep(3)
        #print("---------------------开始滑屏--------------------")
        self.d.swipe(x/5 * 4,y/5 * 4,x/5*4,y/5*1,1,50)
        self.d.swipe(x/5 * 4,y/5 * 4,x/5*4,y/5*1,1,50)
        #print("---------------------滑屏结束-----------------------")
        self.d.implicitly_wait(5)
        #2.通过class和下标点击系统(开发者模式)
        n1 = self.d(className='android.widget.RelativeLayout').count
        self.d(className='android.widget.RelativeLayout')[n1 - 1].click()
        #self.d(className = 'android.widget.LinearLayout',index = '18').click()
        #3.点击语言和输入法
        n2 = self.getLanguageindex()
        self.d(className = 'android.widget.LinearLayout',index = n2).click()
        time.sleep(2)
        #4.点击语言
        self.d(className = 'android.widget.RelativeLayout',index = '1').click()
        time.sleep(2)
        #5.点击添加语言(此时页面仅可存在一个语言,其他语言需提前删除)(需判断目前显示的语言是否和要搜索的一致)
        self.d(resourceId = 'com.android.settings:id/add_language').click()
        #6.点击搜索
        self.d(resourceId = 'android:id/locale_search_menu').click()
        self.savelog()
        #7.输入需要更换的语言(此时要注意一个语言下面还有分支的情况)
        # Changelanguage = 'Čeština'  #Suomi Akan
        time.sleep(3)
        # 7.1 单语言切换
        self.Changelanguage = Changelanguage
        if "/" not in self.Changelanguage:
            self.d(resourceId='android:id/search_src_text').send_keys(self.Changelanguage)
            time.sleep(2)
            clickelecment = self.d(resourceId='android:id/locale').exists
            if clickelecment:
                self.d.implicitly_wait(5)
                # 8.1选择更换的语言,text要是选择的语言,有的语言会有推荐语言列表
                self.d(resourceId='android:id/locale').click()
                time.sleep(5)
                # 如果当前语言为多语言,而表格中输入的是单语言,会进行判断
                judgeSearch = self.d(resourceId='com.android.settings:id/add_language').exists
                logger.debug('------------------判断了' + str(judgeSearch) + '----------------', exc_info=True)
                # print("判断了",judgeSearch)
                if judgeSearch:
                    pass
                elif str(judgeSearch) == "False":
                    logger.debug('------------------切换语言失败,请检查当前语言在表格是否漏填次语言------------------', exc_info=True)
                    print("切换语言失败,请检查当前语言在表格是漏填次语言")
                    self.errorScreenshorts("切换失败", self.Changelanguage)
                    self.d.press("home")
                    return "faile"
            else:
                logger.debug('-----------------当前设备不存在此语言或当前设备语言为此语言------------------', exc_info=True)
                print("当前设备不存在此语言或当前设备语言为此语言")
                self.errorScreenshorts("切换失败", self.Changelanguage)
                time.sleep(2)
                self.d.press("home")
                return "fail"
        self.savelog()
        time.sleep(1)
        # 7.2 多语言切换(英语有很多页,需要滑动的,分开操作)
        if "/" in self.Changelanguage:
            self.Changelanguage = self.Changelanguage.replace("/", "-")
            # print("含有/符号的value:{}".format(self.Changelanguage))  # 把含有/的value打印出来
            multilingual = self.Changelanguage.split("-")  # 分割好的语言放在这个里面
            # print("--------------------------------")
            # print("分割的", multilingual)
            hostLanguage = multilingual[0]  # 获取多语言的主语言
            secondLanguage = multilingual[1]  # 获取多语言的子语言
            # print("secondLanguage:{}".format(secondLanguage))
            time.sleep(3)
            if multilingual[0] == "English":
                self.d(resourceId='android:id/search_src_text').send_keys(hostLanguage)
                self.d.implicitly_wait(5)
                # 8.1点击主语言进入次语言的选择界面
                self.d(resourceId='android:id/locale', text=hostLanguage).click()
                time.sleep(2)
                # 寻找子语言,如果子语言不存在,则滚动屏幕,直到找到子语言,找到子语言则跳出循环,进行后面的操作
                flag = True
                while flag:
                    # 判断元素是否存在
                    time.sleep(5)
                    judgeElement = self.d(resourceId='android:id/locale', text=secondLanguage).exists
                    if judgeElement:
                        logger.debug('---------------次语言查找成功----------------', exc_info=True)
                        # print("---------------次语言查找成功----------------")
                        self.d(resourceId='android:id/locale', text=secondLanguage).click()
                        flag = False
                    else:
                        x = self.sizeTuple[0]  # 获取屏幕的宽
                        y = self.sizeTuple[1]  # 获取屏幕的高
                        logger.debug('--------------滑屏寻找元素--------------', exc_info=True)
                        # print("--------------滑屏寻找元素--------------")
                        # 1.进入设置之后,划动屏幕找到System
                        self.d.swipe(x / 5 * 4, y / 5 * 4, x / 5 * 4, y / 5 * 3, 1, 50)
                        self.d.swipe(x / 5 * 4, y / 5 * 4, x / 5 * 4, y / 5 * 3, 1, 50)
            else:  # 不是英语的其他多语言
                self.d(resourceId='android:id/search_src_text').send_keys(hostLanguage)
                # print("hostLanguage:{}".format(hostLanguage))
                self.d.implicitly_wait(5)
                # 8.1点击主语言进入次语言的选择界面
                hostLanguageElement = self.d(resourceId='android:id/locale', text=hostLanguage)
                judgelement = hostLanguageElement.exists
                if judgelement:
                    hostLanguageElement.click()
                    time.sleep(2)
                    secondLangeageElement = self.d(resourceId='android:id/locale', text=secondLanguage)
                    judgeSecondLangeage = secondLangeageElement.exists
                    if judgeSecondLangeage:
                        secondLangeageElement.click()
                    else:
                        logger.debug('-----------------当前语言不存在该次语言,或当前语言为此语言------------------', exc_info=True)
                        print("当前语言不存在该次语言,或当前语言为此语言")
                        self.errorScreenshorts("切换语言失败", self.Changelanguage)
                        time.sleep(2)
                        self.d.press("home")
                        return "fail"
                else:
                    logger.debug('-----------------当前设备不存在此语言或当前设备语言为此语言------------------', exc_info=True)
                    print("当前设备不存在此语言或当前设备语言为此语言")
                    self.errorScreenshorts("切换语言失败", self.Changelanguage)
                    time.sleep(2)
                    self.d.press("home")
                    return "fail"
        #print("准备点击小点")
        #9.选择右上角的三个小点,remove
        self.d(className = 'android.widget.ImageButton',index='1').click()
        #print("点好了")
        #10.点击移除(把选择之前的语言移除掉)
        self.d(resourceId = 'android:id/content').click()
        time.sleep(3)
        #11.勾选之前的语言(也就是第一个),这样把第一个删除之后,现在的语言就是需要更换的语言
        self.d(className = 'android.widget.RelativeLayout',index = '0').click() #点击第一个语言
        self.d(className = 'android.widget.TextView',index = '0').click() #点击删除
        #12.由于点击第一个删除会触发系统提示弹窗,则勾选ok就好
        self.d(resourceId = 'android:id/button1',index = '1').click()
        time.sleep(1)
        self.d.press("back") #返回到语言和输入法界面
        time.sleep(1)
        self.d.press("back") #返回到系统界面(开始进入系统更新对比)
        logger.debug('-------------------------开始进入系统更新对比------------------', exc_info=True)
        #print("-------------------------开始进入系统更新对比------------------")
        #13.进入系统更新界面
        n3 = self.d(className='android.widget.RelativeLayout').count
        n4 = self.getUpdateindex()
        self.d(className='android.widget.RelativeLayout')[n3 - n4].click()
        #self.d(className = 'android.widget.LinearLayout',index = '8').click()
        self.savelog()
        #14.获取提示信息,先判断提示信息在不在,不在则返回该设备无更新提示信息
        judgemsg = self.d(resourceId = 'com.lenovo.ota:id/text_new_version_content').exists
        if judgemsg:
            WarningText = self.d(resourceId = 'com.lenovo.ota:id/text_new_version_content').get_text(timeout=5)
            # print(WaringText)
            return WarningText
        else:
            print("当前设备无更新提示信息...")
            text1 = self.d(resourceId = 'com.lenovo.ota:id/current_version').get_text(timeout=2)
            text2 = self.d(resourceId = 'com.lenovo.ota:id/current_version_content').get_text(timeout=2)
            WarningText = '{}\n{}'.format(text1,text2)
            return WarningText
    # 15.把获取到的信息写入到表格中,使用获取到的信息和表格里面的信息进行对比
    @errorlog
    def judgeResult(self):
        self.savelog()
        logger = logging.getLogger()
        #获取select为1的行数和语言的键值对  eg.{3: 'Latviešu', 4: '日本語'}
        languageList = RWExcel(self.resultExcelPath).list_dic()
        #print(languageList)
        languageTotal = len(languageList)
        count = 0
        for key, value in languageList.items():
            #print("index:{},value:{}".format(key, value))
            # key作为第几行直接输入
            #print("---------------------开始切换语言-------------")
            count += 1
            percent = format(count/languageTotal, '.1%')
            #value = str(value)
            logger.debug("-------------------------正在切换语言:{},请等待-------------------".format(value), exc_info=True)
            print("-------正在切换语言:{},请等待......".format(value))
            msg = Run.readWarning(value)
            #print(msg)
            logger.debug('-----------------------开始把warning信息写入到对应表格中------------------', exc_info=True)
            #print("-------------------开始把warning信息写入到对应表格中-------------------")
            write = Write_excel(r'{}'.format(self.resultExcelPath), key, msg)
            #把获取到的warning信息写入进入表格
            write.write()
            logger.debug('---------------------Warning信息写入成功------------------', exc_info=True)
            #print("-------------------Warning信息写入成功--------------------------")
            logger.debug('---------------------开始对比系统提示与标准描述模板是否一致--------------', exc_info=True)
            #print("----------------------开始对比系统提示与标准描述模板是否一致----------------")
            logger.debug('----------------开始把测试结果写入到对应表格中---------------------', exc_info=True)
            #print("-------------------开始把测试结果写入到对应表格中-------------------")
            #把对比之后的测试结果写入到表格
            result = write.write_result()
            logger.debug('-----------------------当前切换语言测试结果写入成功-----------------', exc_info=True)
            #print("-------------------当前切换语言测试结果写入成功--------------------------")
            logger.debug('-------------------------截图保存--------------------', exc_info=True)
            #print("-------------------截图保存--------------------------")
            # 16.获取到信息之后截屏,截图该屏幕并保存到同目录的screen文件中,图片名称为时间+语言
            # nowTime = datetime.datetime.now().strftime('%m-%d-%H-%M-%S')
            self.d.screenshot("{}\第{}行_{}_{}.jpg".format(self.makeFolderPath, key + 1, self.Changelanguage,result))
            picturePath = "{}\第{}行_{}_{}.jpg".format(self.makeFolderPath, key + 1, self.Changelanguage, result)
            #print(picturePath)
            write.write_hyperlink(picturePath)
            logger.debug('------------------------当前语言切换结束------------------', exc_info=True)
            #print("-------------------当前语言切换结束--------------------------")
            print("------------------- 当前进度:{}/{},完成率:{} ----------------------".format(count, languageTotal, percent))
            print("\n")
            time.sleep(3)
            self.d.press("home")
            self.savelog()
            time.sleep(3)
            if count == languageTotal:
                print("-----------------已完成100%,所有语言切换完毕-----------------------")
                input("请点击回车按键关闭当前窗口:")
if __name__ == '__main__':
    Run = readWarningTest()
    Run.copyExcel()
    Run.connect()
    Run.judgeResult()

附:小知识

[ python]获取目录下的最新文件夹/文件

def new_report(test_report):
     lists = os.listdir(test_report)      #列出目录的下所有文件和文件夹保存到lists
     print(list)
     lists.sort(key=lambda fn:os.path.getmtime(test_report + "\\" + fn))  #按时间排序
     file_new = os.path.join(test_report,lists[-1])        #获取最新的文件保存到file_new
     print(file_new)
     return file_new
 if __name__=="__main__":
     test_report="path"     #目录地址
    new_report(test_report)
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3天前
|
开发者 Python
Python中__init__.py文件的作用
`__init__.py`文件在Python包管理中扮演着重要角色,通过标识目录为包、初始化包、控制导入行为、支持递归包结构以及定义包的命名空间,`__init__.py`文件为组织和管理Python代码提供了强大支持。理解并正确使用 `__init__.py`文件,可以帮助开发者更好地组织代码,提高代码的可维护性和可读性。
8 2
|
19天前
|
Java Python
> python知识点100篇系列(19)-使用python下载文件的几种方式
【10月更文挑战第7天】本文介绍了使用Python下载文件的五种方法,包括使用requests、wget、线程池、urllib3和asyncio模块。每种方法适用于不同的场景,如单文件下载、多文件并发下载等,提供了丰富的选择。
|
19天前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
14天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
9天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
2天前
|
存储 人工智能 数据挖掘
从零起步,揭秘Python编程如何带你从新手村迈向高手殿堂
【10月更文挑战第32天】Python,诞生于1991年的高级编程语言,以其简洁明了的语法成为众多程序员的入门首选。从基础的变量类型、控制流到列表、字典等数据结构,再到函数定义与调用及面向对象编程,Python提供了丰富的功能和强大的库支持,适用于Web开发、数据分析、人工智能等多个领域。学习Python不仅是掌握一门语言,更是加入一个充满活力的技术社区,开启探索未知世界的旅程。
11 5
|
2天前
|
人工智能 数据挖掘 开发者
探索Python编程:从基础到进阶
【10月更文挑战第32天】本文旨在通过浅显易懂的语言,带领读者从零开始学习Python编程。我们将一起探索Python的基础语法,了解如何编写简单的程序,并逐步深入到更复杂的编程概念。文章将通过实际的代码示例,帮助读者加深理解,并在结尾处提供练习题以巩固所学知识。无论你是编程新手还是希望提升编程技能的开发者,这篇文章都将为你的学习之旅提供宝贵的指导和启发。
|
14天前
|
弹性计算 安全 小程序
编程之美:Python让你领略浪漫星空下的流星雨奇观
这段代码使用 Python 的 `turtle` 库实现了一个流星雨动画。程序通过创建 `Meteor` 类来生成具有随机属性的流星,包括大小、颜色、位置和速度。在无限循环中,流星不断移动并重新绘制,营造出流星雨的效果。环境需求为 Python 3.11.4 和 PyCharm 2023.2.5。
|
7天前
|
数据处理 Python
从零到英雄:Python编程的奇幻旅程###
想象你正站在数字世界的门槛上,手中握着一把名为“Python”的魔法钥匙。别小看这把钥匙,它能开启无限可能的大门,引领你穿梭于现实与虚拟之间,创造属于自己的奇迹。本文将带你踏上一场从零基础到编程英雄的奇妙之旅,通过生动有趣的比喻和实际案例,让你领略Python编程的魅力,激发内心深处对技术的渴望与热爱。 ###
|
10天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第24天】本文将带你进入Python的世界,从最基础的语法开始,逐步深入到实际的项目应用。我们将一起探索Python的强大功能和灵活性,无论你是编程新手还是有经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python的奇妙之旅吧!