-
一、pyautogui是什么?pyautogui是一个Python模块,可以模拟用户在屏幕上的鼠标和键盘操作。它可以自动化鼠标和键盘输入,可以用于各种自动化任务,例如GUI测试、自动化数据输入、自动化游戏玩法等。pyautogui提供了一组函数来控制鼠标和键盘,例如移动鼠标、单击、双击、右键单击、按下和释放键等。它还提供了一些额外的功能,例如捕捉屏幕截图、识别颜色和图像等,以及其他一些实用工具,例如获取屏幕尺寸和鼠标位置。二、使用步骤1.安装和引入库1pip install pyautogui1import pyautogui2.基本操作(1)鼠标控制PyAutoGUI可以模拟鼠标的点击和移动。以下是一些基本操作: moveTo(x, y):将鼠标移动到屏幕上的指定位置。 click(x=None, y=None, button='left'):在指定位置单击鼠标左键、右键或中键。 doubleClick(x=None, y=None, button='left'):在指定位置双击鼠标左键、右键或中键。 rightClick(x=None, y=None):在指定位置单击鼠标右键。 middleClick(x=None, y=None):在指定位置单击鼠标中键。 dragTo(x, y, duration=0.5):将鼠标拖动到指定位置。'实例:import pyautogui # 将鼠标移动到屏幕中央 pyautogui.moveTo(pyautogui.size()[0]/2, pyautogui.size()[1]/2) # 在屏幕中央单击鼠标左键 pyautogui.click()2)键盘控制PyAutoGUI还可以模拟键盘的输入。以下是一些基本操作:typewrite(message, interval=0.1):将字符串输入到键盘,可以设置键入每个字符的时间间隔。 press(key):按下指定的键。 release(key):释放指定的键。 hotekey('ctrl',key)::按下组合键以下是一个例子,演示如何将“Hello, world!”字符串键入到计算机上: import pyautogui # 将“Hello, world!”字符串键入计算机 pyautogui.typewrite('Hello, world!') # 模拟按下键盘的A键 pyautogui.press('a') # 模拟释放键盘的A键 pyautogui.release('a') #组合键 pyautogui.hotkey('ctrl','v') (3)屏幕截图PyAutoGUI可以截取屏幕上的图像。以下是一个基本操作:screenshot():截取屏幕上的图像,并返回PIL图像对象。以下是一个例子,演示如何截取整个屏幕的图像: import pyautogui # 截取整个屏幕 screenshot = pyautogui.screenshot() # 显示截图 screenshot.show()
-
我们需要 exifread 库,这个就是用来提取 GPS 信息的。直接 pip install exifread 来安装就好了。我用前段时间朋友在三亚拍的这个骆驼照片来做个演示,看看能不能定位到三亚。【用的是 iphone 手机拍摄的,其它的手机是否能提取出 GPS 信息需要大家来试试】注:如果图片被压缩了的话会破坏里面的二进制信息,肯定就不能提取了哦!如果程序运行报 KeyError: '纬度' 错误,可能就是这个原因,可以参照文章结尾的属性查看方法来判断一下。我们的原理就是: 先把图片以二进制的格式读取出来,然后通过 exifread 库把里面的 GPS 信息提取出来,再以特定的格式打印出来,最后直接复制里面的经纬度信息【地图查询需要把把纬度放前面,所有我就先把纬度打出来了】在支持通过经纬度来查位置的地图里一查就能定位到了。import exifread import re # 读取图片为二进制格式 f = open("luotuo.JPG","rb") tags = exifread.process_file(f) # GPS信息 GPS = {} # 拍摄时间 Data = "" for tag,value in tags.items(): # 获取纬度信息 if re.match('GPS GPSLatitude', tag): try: match_result=re.match('\[(\w*), (\w*), (\w.*)/(\w.*)\]', str(value)).groups() GPS['纬度'] = str(int(match_result[0])) + " " + str(int(match_result[1])) + " " + str(int(match_result[2])/int(match_result[3])) except: GPS['纬度'] = str(value) # 获取纬度信息 elif re.match('GPS GPSLongitude', tag): try: match_result=re.match('\[(\w*), (\w*), (\w.*)/(\w.*)\]',str(value)).groups() GPS['经度'] = str(int(match_result[0])) + " " + str(int(match_result[1])) + " " + str(int(match_result[2])/int(match_result[3])) except: GPS['经度'] = str(value) # 获取高度 elif re.match('GPS GPSAltitude', tag): GPS['高度'] = str(value) # 获取拍摄时间 elif re.match('Image DateTime', tag): Data = str(value) # 打印信息 print("纬 经 度:" + GPS['纬度'] + "," + GPS['经度']) print("拍摄时间:" + Data)
-
受试者工作特征(Receiver Operating Characteristic,ROC)的基本知识ROC曲线可以用来评估分类器的输出质量。ROC曲线Y轴为真阳性率,X轴为假阳性率。这意味着曲线的左上角是“理想”点——假阳性率为0,真阳性率为1。上述的理想情况实际中很难存在,但它确实表示面积下曲线(AUC)越大通常分类效率越好。ROC曲线的“陡度”也很重要,坡度越大,则越有降低假阳性率,升高真阳性率的趋势。ROC曲线通常用于二元分类中研究分类器的输出(也可在多分类中使用,需要对标签进行二值化【比如ABC三类,进行分类时将标签进行二值化处理[A(1)、BC(0)】、【B(1)、AC(0)】、【C(1)、AB(0)】,比如本文不作讨论)。python 实现绘制ROC曲线主要基于python 的sklearn库中的两个函数,roc_curv和auc两个函数。roc_curv 用于计算出fpr(假阳性率)和tpr(真阳性率)auc用于计算曲线下面积,输入为fpr、和tprroc_curv函数详解roc_curve(y_true, y_score, pos_label=None, sample_weight=None,drop_intermediate=True)输入值y_true :一个和样本数量一致的一维向量,数据是正确的二元标签。如果标签不是{- 1,1}或{0,1},则可以显式指定pos_label。y_score:一个样本数量一致的一维向量,目标分数可以是阳性类的概率估计、置信度值或决策的非阈值度量(在某些分类器上由“decision_function”返回,比如SVM)。简单的理解就是对测试集进行分类后得到的一个用于衡量该类是阳性还是阴性的分数度量,分类器也是根据这个分数来判断测试集是阳性样本还是阴性样本,因此通常都可以在分类器的中间过程拿到这个分数。pos_label:样本标签,如果y_true不满足{0,1},{-1,1}标签时则需要通过该参数指定那些是阳性样本,其余的则为阴性样本,默认不输入。sample_weight:一个样本数量一致的一维向量,指定每个样本的权重,默认不输入。drop_intermediate:为true时(默认= True)会删除一些不会出现在ROC曲线上的次优阈值。返回值fpr:假阳性率序列,数量与thread一致的一维向量。tpr:真阳性率序列,数量与thread一致的一维向量。thread:该序列是一个递减序列,在每一个阈值下对y_score进行划分,大于的视为阳性,小于的视为阴性,从而计算出该阈值下的fpr。代码示例# 导包 import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import roc_curve, auc # 计算 fpr, tpr, thread = roc_curve(y_test, y_score) roc_auc[i] = auc(fpr, tpr) # 绘图 plt.figure() lw = 2 plt.plot(fpr, tpr, color='darkorange', lw=lw, label='ROC curve (area = %0.2f)' % roc_auc) plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver operating characteristic example') plt.legend(loc="lower right") plt.savefig('roc.png',) plt.show()y_test 数据示例:0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1y_score:数据示例:-0.763011 -0.202245 0.118015 -0.907809 -0.0111619 -0.604873 0.0228349 -0.610769 -0.375728 -0.470174 -0.422242 -0.335587 -0.227239 -0.0785673 -0.533834 0.121637 -0.713569 -0.551115 0.379913 -0.111076
-
1. 简介在Python中,map()是一个内置函数,用于对可迭代对象中的每个元素应用一个函数,并返回一个结果列表。它可以将一个序列中的每个元素都映射到另一个值上,非常灵活和实用。 本文将从基础的使用方法到高级的技巧,全面介绍Python中map()方法的使用。2. 基本用法2.1 语法和参数map()函数的基本语法如下:1map(function, iterable)function:一个函数或可调用对象,用于对每个元素进行操作。iterable:一个可迭代对象,如列表、元组等。2.2 示例我们来看一个简单的示例,将一个列表中的每个元素都加上2:def add_two(x): return x + 2 numbers = [1, 2, 3, 4, 5] result = map(add_two, numbers) print(list(result))输出结果为:[3, 4, 5, 6, 7]。 在上面的例子中,我们定义了一个add_two()函数,它将传入的参数加上2并返回。然后,我们使用map()函数将add_two()函数应用到numbers列表的每个元素上,得到一个新的结果列表。3. Lambda函数与map的结合使用在实际应用中,我们常常使用匿名函数(Lambda函数)结合map()函数,以便更简洁地处理数据。3.1 示例我们来看一个使用Lambda函数和map()函数计算列表中每个元素的平方的示例:numbers = [1, 2, 3, 4, 5] result = map(lambda x: x ** 2, numbers) print(list(result))输出结果为:[1, 4, 9, 16, 25]。 在上面的例子中,我们使用Lambda函数定义了一个匿名函数,它将传入的参数平方并返回。然后,我们使用map()函数将Lambda函数应用到numbers列表的每个元素上,得到一个新的结果列表。 Lambda函数与map()函数的结合使用可以大大简化代码,使代码更加清晰和易读。4. 多个可迭代对象的处理除了处理单个可迭代对象外,map()函数还可以处理多个可迭代对象,并将它们的对应元素依次传递给函数进行操作。4.1 示例我们来看一个使用map()函数处理两个列表的示例,将两个列表中的对应元素相加:numbers1 = [1, 2, 3, 4, 5] numbers2 = [10, 20, 30, 40, 50] result = map(lambda x, y: x + y, numbers1, numbers2) print(list(result))输出结果为:[11, 22, 33, 44, 55]。 在上面的例子中,我们使用Lambda函数定义了一个匿名函数,它将两个参数相加并返回。然后,我们使用map()函数将Lambda函数应用到numbers1和numbers2两个列表的对应元素上,得到一个新的结果列表。 通过处理多个可迭代对象,我们可以实现更加复杂的数据操作和处理。5. map对象与列表转换map()函数返回的是一个map对象,它是一个惰性求值的对象,只有在需要时才会生成对应的结果。5.1 示例我们来看一个使用map()函数生成的map对象的示例,将其转换为列表:numbers = [1, 2, 3, 4, 5] result = map(lambda x: x * 2, numbers) print(result) # 输出结果:<map object at 0x00000123456789> print(list(result)) # 输出结果:[2, 4, 6, 8, 10]在上面的例子中,我们先打印result对象,发现它是一个map对象。然后,我们使用list()函数将result对象转换为列表,得到最终的结果。 通过将map对象转换为列表,我们可以随时查看和使用生成的结果。6. 注意事项在使用map()函数时,有一些注意事项需要注意:map()函数的返回值是一个map对象,需要使用list()等函数进行转换。map()函数将函数应用于每个元素时,会按顺序处理,一一对应。输入的可迭代对象的长度应相等,否则会截断到最短长度。
-
pop() 可以「删除」列表中的元素(默认最后一个)。语法1list.pop( index )参数index :(可选)需要删除的元素的索引值返回值返回被删除的元素实例:删除列表中第一个元素list1 = [1, 2, 3] list1.pop(1) print(list1)输出:[1, 3]1、按照索引删除元素pop() 可以根据指定的「索引」,删除对应「位置」的元素。1.1、正数索引索引为「正数」时,从 0 开始,按照从左往右的顺序删除list1 = [1, 2, 3, 4] print('删除前:', list1) list1.pop(0) print('删除后:', list1)输出:删除前: [1, 2, 3, 4]删除后: [2, 3, 4]指定的索引不能超过列表的「长度」,否则会报错 IndexError: pop index out of range1.2、负数索引索引为「负数」时,从 1 开始,按照从右往左的顺序删除list1 = [1, 2, 3, 4] print('删除前:', list1) list1.pop(-1) print('删除后:', list1)输出:删除前: [1, 2, 3, 4]删除后: [1, 2, 3]索引超过列表「长度」时,同样会报错 IndexError: pop index out of range1.3、不指定索引「不指定索引」时,默认是 -1,也就是删除最后一个元素list1 = [1, 2, 3, 4] print('删除前:', list1) list1.pop() print('删除后:', list1)输出:删除前: [1, 2, 3, 4]删除后: [1, 2, 3]2、返回被删除的元素pop() 可以理解为「弹出」元素,它会返回被删除的元素,我们可以打印被删除的元素,来判断有没有删错。list1 = [1, 2, 3, 4] print(list1.pop())输出:43、不同类型的元素上面的案例中,我们删除的都是一个元素,这个很好理解。对于列表中「嵌套」列表这类情况,会把列表整体当做一个元素删掉,比如下面这样:list1 = [1, 2, [1, 2, 3], 4] print('删除前:', list1) list1.pop(2) print('删除前:', list1)输出:删除前: [1, 2, [1, 2, 3], 4]删除前: [1, 2, 4]列表中嵌套元祖、字典时,也同样整个删除list1 = [1, 2, {1, 2, 3}, 4] print('删除前:', list1) list1.pop(2) print('删除前:', list1)输出:删除前: [1, 2, {1, 2, 3}, 4]删除前: [1, 2, 4]即使嵌套很多层,也会整个删除list1 = [1, 2, [1, [1, [1, 2]]], 4] print('删除前:', list1) list1.pop(2) print('删除前:', list1)输出:删除前: [1, 2, [1, [1, [1, 2]]], 4]删除前: [1, 2, 4]4、常见错误列表的 pop() 一次只能删除一个元素,否则会报错 TypeError: pop expected at most 1 argumentpop() 的参数必须是int,只能根据索引删除元素,否则会报错 TypeError: ‘str’ object cannot be interpreted as an integer
-
在日常业务处理中,我们经常会面临将不同系统中的数据进行匹配和比对的情况,本文将介绍如何使用Python的Pandas库来处理这个问题,需要的可以参考一下+目录引言在日常业务处理中,我们经常会面临将不同系统中的数据进行匹配和比对的情况。特别是在涉及到客户管理的领域,我们需要确保两个系统中的客户记录是准确、一致和无重复的。本文将介绍如何使用Python的Pandas库来处理这个问题。我们将以一个示例情景为例,假设我们有一个MR系统和一个客户系统,这两个系统都有一个客户ID和客户名称的列。我们的目标是根据客户ID匹配后,计算两列客户名称的相似度。实现步骤步骤1:导入必要的库首先,我们需要导入必要的库。除了Pandas库,我们还将使用fuzzywuzzy库来计算字符串相似度。import pandas as pd from fuzzywuzzy import fuzz步骤2:创建示例数据集为了演示我们的方法,让我们创建一个简单的示例数据集。假设我们有一个包含MR系统客户信息的DataFrame,其中包括客户ID和客户姓名的列。同样地,我们还有一个包含客户系统客户信息的DataFrame,其中也包括客户ID和客户姓名的列。mr_system = pd.DataFrame({ '客户ID': ['1001', '1002', '1003', '1004', '1005'], '客户姓名': ['中国电信', '中石油股份有限公司', '中国工商银行', '阿里巴巴集团', '腾讯控股有限公司'] }) customer_system = pd.DataFrame({ '客户ID': ['1001', '1002', '1003', '1004', '1005'], '客户姓名': ['中国电信通信集团', '中石化石油化工集团', '中国建设银行股份有限公司', '京东集团有限公司', '百度在线网络技术'] })步骤3:数据匹配和相似度计算现在,我们将根据客户ID将这两个数据集进行匹配,并计算两列客户名称的相似度。我们可以使用Pandas的merge()方法来合并两个数据集,并根据客户ID进行匹配。matched_data = pd.merge(mr_system, customer_system, on='客户ID')然后,我们可以使用fuzzywuzzy库的fuzz.ratio()方法来计算两列客户名称的相似度。该方法返回一个介于0到100之间的分数,表示两个字符串的相似程度。matched_data['相似度'] = matched_data.apply(lambda row: fuzz.ratio(row['客户姓名_x'], row['客户姓名_y']), axis=1)步骤4:结果展示最后,我们可以打印出匹配后的数据和相似度结果。print(matched_data[['客户ID', '客户姓名_x', '客户姓名_y', '相似度']])结果示例: 客户ID 客户姓名_x 客户姓名_y 相似度0 1001 中国电信 中国电信通信集团 671 1002 中石油股份有限公司 中石化石油化工集团 332 1003 中国工商银行 中国建设银行股份有限公司 443 1004 阿里巴巴集团 京东集团有限公司 294 1005 腾讯控股有限公司 百度在线网络技术 0步骤5:查询相似度大于40的客户matched_data.loc[matched_data.相似度 > 40]输出: 客户ID 客户姓名_x 客户姓名_y 相似度0 1001 中国电信 中国电信通信集团 672 1003 中国工商银行 中国建设银行股份有限公司 44结论通过使用Pandas库和字符串相似度算法,我们可以方便地计算两个系统中客户名称的相似度。这有助于我们发现和处理重复或相似的客户记录,提高数据的准确性
-
get() 可以根据键「获取值」语法1dict.get( key, value )参数key :(必选)指定要搜索的键value :(可选)如果键不存在,就返回指定内容返回值如果键存在,就返回键对应的值如果键不存在,就返回指定内容或None实例:根据键获取字典的值dict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1.get('key1'))输出:value11、设置默认返回值get() 可以指定「默认」的「返回值」,键不存在时,它不会报错,而是返回一个默认值,这样的好处是,程序在运行时不会出现异常的情况。「不指定」返回值,键不存在时,默认返回 Nonedict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1.get('key3')) print(dict1.get('key3', None))输出:NoneNone「指定」返回值,键不存在时,返回会指定的返回值dict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1.get('key3', '指定返回值'))输出:指定返回值返回值可以是整型、字符串、元祖、列表等各种数据类型dict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1.get('key3', 1)) print(dict1.get('key3', 1.1)) print(dict1.get('key3', True)) print(dict1.get('key3', [1, 2])) print(dict1.get('key3', (1, 2))) print(dict1.get('key3', {1, 2}))输出:11.1True[1, 2](1, 2){1, 2}2、嵌套字典取值字典中「嵌套」字典时,可以多次调用 get() ,来取值。dict1 = {'key1': 'value1', 'key2': {'key3': 'value3'}} print(dict1.get('key2').get('key3')) # 等价于这样 result = dict1.get('key2') print(result) result1 = result.get('key3') print(result1)输出:value3{'key3': 'value3'}value33、get() 和 dict[key] 的区别get() 和 dict[key] 都可以根据键获取字典的值,不同的是get() 的键在字典中不存在时,会返回「None」 或 「指定内容」dict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1.get('key3')) print(dict1.get('key3', '指定内容'))输出:None指定内容dict[key] 的键在字典中不存在时,会「报错」 KeyError: ‘key3’dict1 = {'key1': 'value1', 'key2': 'value2'} print(dict1['key3'])4、统计元素计数get() 可以「统计」列表元素出现的「个数」,将统计结果保存到字典中dict1 = {} list1 = ['¥', '¥', '¥', '$', '$', '$', '$', '$'] for i in list1: dict1[i] = dict1.get(i, 0) + 1 print(dict1)输出:{'¥': 3, '$': 5}
-
add() 函数可以给集合「添加」元素。语法1set.add( element )参数element :(必选)需要添加的元素返回值None,没有返回值,值修改原集合。实例:向集合中添加元素set1 = {1, 2, 3} set1.add(4) print(set1)输出:{1, 2, 3, 4}1、元素的顺序add() 并不是将元素插入到集合的「末尾」。因为集合「不保证」元素的「顺序」,所以我们每次打印,元素的位置都会发生变化。set1 = {1, 2, 3} set1.add('ZhangSan') set1.add('LiSi') set1.add('WangWu') set1.add('QianLiu') set1.add('SunQi') print(set1)输出:{1, 2, 3, 'ZhangSan', 'QianLiu', 'WangWu', 'LiSi', 'SunQi'}从输出结果可以看到,元素并非按照添加的顺序展示;尝试多次打印,会发现每次的顺序都不一样。需要注意的是,使用「循环」的方式打印,元素的顺序就不会再发生变化set1 = {1, 2, 3} set1.add('ZhangSan') set1.add('LiSi') set1.add('WangWu') set1.add('QianLiu') set1.add('SunQi') i = 0 while i < 10: print(set1) i += 1输出:{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}{'WangWu', 1, 2, 3, 'SunQi', 'ZhangSan', 'LiSi', 'QianLiu'}2、可以添加的元素类型add() 添加的元素,可以是「字符串」、「元组」、「bytes类型」,不能是列表、集合、字典类型。set1 = {1, 2, 3} set1.add('str') set1.add((4, 5, 6)) set1.add(b'123') print(set1)输出:{1, 2, 3, (4, 5, 6), 'str', b'123'}添加不允许的元素类型时,会报错 TypeError: unhashable type: ‘list’3、添加重复的元素集合中的元素不允许「重复」,如果添加集合中「已经存在」的元素,则不会执行添加的操作,当然,也不会报错。set1 = {1, 2, 3} set1.add(3) print(set1)输出:{1, 2, 3}4、一次只能添加一个元素add() 只接收一个参数,这意味着每次只能添加「一个元素」,否则会报错 TypeError: add() takes exactly one argumentset1.add(1, 2)
-
一、管道机制Scikit-learn的Pipeline类是一种方便的工具,它允许你将多个步骤(如数据预处理和模型训练)封装在一个估计器中。这样可以确保我们的代码更整洁,而且能够保持训练和预测阶段的一致性。下面的代码展示了如何使用Pipeline来封装预处理和模型训练步骤:from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC pipe = Pipeline([ ('scaler', StandardScaler()), ('svm', SVC()) ]) pipe.fit(X_train, y_train) predictions = pipe.predict(X_test)from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC pipe = Pipeline([ ('scaler', StandardScaler()), ('svm', SVC()) ]) pipe.fit(X_train, y_train) predictions = pipe.predict(X_test)from sklearn.metrics import make_scorer def custom_loss_func(y_true, y_pred): # Insert your own calculation here return loss_value my_scorer = make_scorer(custom_loss_func, greater_is_better=False) grid_search = GridSearchCV(estimator, param_grid, scoring=my_scorer)三、模型的保存和加载在大型项目中,我们可能需要保存训练好的模型,并在稍后的时间或在不同的环境中重新加载。Scikit-learn使用了Python的内置模块pickle来实现模型的保存和加载。from sklearn.externals import joblib # Save the model joblib.dump(clf, 'model.pkl') # Load the model clf = joblib.load('model.pkl')四、使用FeatureUnion组合特征有时候,我们可能希望对数据的不同子集应用不同的预处理步骤,然后将结果组合成一个特征集。Scikit-learn的FeatureUnion类提供了一种实现这个功能的方法。from sklearn.pipeline import FeatureUnion from sklearn.decomposition import PCA from sklearn.decomposition import KernelPCA combined_features = FeatureUnion([ ("pca", PCA(n_components=3)), ("kernel_pca", KernelPCA(n_components=3)), ]) X_features = combined_features.fit(X, y).transform(X)
-
python实现kafka生产消息 python3环境准备 1. 安装python依赖 pip3 install confluent-kafka pip3 install kafka-python 2. python代码 from confluent_kafka import Producer # Kafka 服务器地址 bootstrap_servers = 'x.x.x.x:21005, x.x.x.x:21005, x.x.x.x:21005' # 创建生产者配置 producer_config = { 'bootstrap.servers': bootstrap_servers } # 创建生产者实例 producer = Producer(producer_config) # 主题和消息列表 topic = 'your_topic' messages = ['Message 1', 'Message 2', 'Message 3'] # 批量发送消息到 Kafka for message in messages: producer.produce(topic, message.encode('utf-8')) 刷新生产者缓冲区 producer.flush() 关闭生产者实例 producer.flush() producer.poll(0) # 等待传递所有消息 producer.flush() 4. 执行命令 ./python3 /opt/sandbox/python_kafkaproducer.py python实现kafka消费消息 1. python代码 from kafka import KafkaConsumer from kafka import KafkaProducer from kafka.errors import KafkaError import sys def start_consumer(consumertopicname): consumer = KafkaConsumer(consumertopicname, group_id='my-group', bootstrap_servers='x.x.x.x:21005,x.x.x.x:21005,x.x.x.x:21005') for message in consumer: print ("%s:%d:%d: key=%s value=%s" % (message.topic, message.partition, message.offset, message.key, message.value)) if name == "main": if len(sys.argv) < 1: print("usage:python3 pythonkafka.py consumertopicname producertopicname") exit(-1) consumertopicname=sys.argv[1] start_consumer(consumertopicname) 2. 执行命令 ./python3 /opt/sandbox/test_spark.py your_topic`(参数填写需要消费的topic) 注: bootstrap_servers填写节点加端口,非安全为21005
-
一、爬虫的原理 爬虫是什么?把互联网上的数据,抓取下来,存到自己的本地。 以百度为例,爬取一个个的网页,存到自己库中,当我们搜索的时候,去百度的数据库中搜索,显示在前端,点击某个页面,直接跳转到真正的地址。 基本原理: 发送http请求(requests)---->返回数据----->解析数据(数据清洗,bs4,re…)---->入库(文件,excel,mysql,redis,mongodb) 注: 爬取数据时,如果被禁止了,一定是你模拟的不像。 爬虫协议: 每个网站,都有爬虫协议,规定了哪些允许你爬,哪些不允许你爬(君子协议) robots.txt---->只是一个协议 反爬: 验证码 封ip 封账号 js逆向:js比较不错 app爬取:加密 app逆向:java,动态调试so文件---->汇编 爬虫所需工具: 请求库:requests,selenium 解析库:正则,beautifulsoup,pyquery 存储库:文件,MySQL,Mongodb,Redis 爬虫常用框架: scrapy 二、请求库requests基本使用 模拟发送http请求(只要http请求有的东西,都可以使用requests发送出去)。 python内置的urllib2、urllib3,不太好用,用起来比较麻烦。 大神基于urllib3封装了requests,python界非常出名的第三方库,只能发送http请求,不能解析; 又封装了一个requets-html库,把request和解析库封装到一起了。 安装:pip3 install requests 1.基本使用 import requests # res对象中会有,响应体,响应头,cookie。。。。 # 请求头中带User-Agent,是客户端类型 # 加入请求头 res = requests.get('https://dig.chouti.com/',headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' }) print(res.text) # 响应体,转成了字符串 with open('a.html','w',encoding='utf-8') as f: f.write(res.text) # 另外一种使用 requests.request('post',cookies={}) 2.带参数的GET请求 # 方式一:get请求参数,直接拼接在路径中 response = requests.get('https://www.baidu.com/s?wd=美女', headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36', }) with open('baidu.html', 'w', encoding='utf-8') as f: f.write(response.text) # 方式二:使用params参数 response = requests.get('https://www.baidu.com/s', params={'wd': '帅哥'}, headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36', }) with open('baidu.html', 'w', encoding='utf-8') as f: f.write(response.text) 3.带参数的GET请求(headers) import requests # res对象中会有,响应体,响应头,cookie。。。。 # 请求头中带User-Agent,是客户端类型 # referer:上一次请求的地址,做图片防盗链 # cookie:cookie信息 # 加入请求头 header={ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36', 'referer':'https://www.lagou.com/wn/zhaopin' } res = requests.get('https://www.lagou.com/gongsi/',headers=header) print(res.text) # 响应体,转成了字符串 referer:比如向这个图片地址发请求,会有referer,检测referer是不是这个网站的,不是则禁止。 4.带参数的GET请求(cookies) # 方式一:带在请求头中 header={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36', 'cookie':'deviceId=web.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqaWQiOiIwZmVlMjk5OS1iMDgzLTRmYzctOTM4MC03YjIzZmVmY2U5YmYiLCJleHBpcmUiOiIxNjIzOTA0ODk5MzM5In0.7cadtBYznS6OgnLwEF8aH0AmtDOoYB1WKDgdU4eYYS0; __snaker__id=VbChmBUEZIVY3FPa; _9755xjdesxxd_=32; YD00000980905869%3AWM_TID=%2FazmF9%2FrClJFEVFBVRN70z7msH6De39Y; Hm_lvt_03b2668f8e8699e91d479d62bc7630f1=1631674964,1634180671,1634183906; gdxidpyhxdE=SmmnuyrMOQB%2B9hzOlIaMPx0O9ZJbqWBllx7aa1OTmRwgGymo94mTYgZ0DrUWw7tfx8qIZmRt01BbIVX2jIc30jqSzPWznXpll6kBokS56266%2FmPg%2BC%5CvNV%2BJhO%5C9ln%2FQdskmo%2FH5A%2BLOADRDACtDp59%5CH51jexwMSIXSA9atTxuJDXOn%3A1634184810108; YD00000980905869%3AWM_NI=WlPwT2GigeoAGFNAH66LZluq3E87sk7E%2Bn6YtGANtE0G%2Bke2f0x6a1rG8kACozd%2FrWBXr3ne%2FBnps6fdDDeTm052UXP1VES3VxQISaL9zd91nvo%2FON%2FVuXS9INJSQYS%2FOG8%3D; YD00000980905869%3AWM_NIKE=9ca17ae2e6ffcda170e2e6ee97c96aadeda38de27286ef8bb3d45a828f8babae8095aea8d0b47e9191e186c42af0fea7c3b92a95b4a098d73a85b7a986ee4b859a82a2cb3ef694968df87bf19bf8d8f261f59be58fb553b8998faff74ff499e58ce83aa6f0b8d7e43bb299f88cc449ada6acd0f15d8288bed4ed6fed9ea291f23ea6bc8ca5e860aff0fbd3d85494ef9aa6d23996a89faad26b90e7b685bc3baeaaa1d0ce46ed8abbb9d2338b9286b4d45391f181a8bb37e2a3; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqaWQiOiJjZHVfNTMyMDcwNzg0NjAiLCJleHBpcmUiOiIxNjM2Nzc1OTIyMTI2In0.o5-Y9-USxFog5sdo1WR1WORUzPkUD4fozEVA_f0WSHU; Hm_lpvt_03b2668f8e8699e91d479d62bc7630f1=1634183939' } # post请求,携带在请求体中的数据 res=requests.post('https://dig.chouti.com/link/vote',data={'linkId': '32667354'},headers=header) #https://dig.chouti.com/link/cancel/vote print(res.text) # 方式二:直接以参数形式传入,cookie会经常用,而且一般是字典形式,提供了一个cookie参数 header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36', } # cookies需要是:Dict or CookieJar object res = requests.post('https://dig.chouti.com/link/vote', data={'linkId': '32667354'}, headers=header,cookies={}) print(res.text) 5.POST请求 # 发送post请求,模拟浏览器的登录行为 header = { 'Referer': 'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' } res = requests.post('http://www.aa7a.cn/user.php', headers=header, data={ 'username': 'xxx@qq.com', 'password': 'xxx', 'captcha': 'fmd8', 'remember': 1, 'ref': 'http://www.aa7a.cn/', 'act': 'act_login', }) # 获取到cookie,登陆过后的cookie cookie = res.cookies print(cookie) # CookieJar res1 = requests.get('http://www.aa7a.cn/', headers=header, cookies=cookie) # res1=requests.get('http://www.aa7a.cn/',headers=header) print('xxx@qq.com' in res1.text) 6.响应Response import requests respone=requests.get('http://www.360buy.com') # respone属性 print(respone.text) # body的内容转成str类型 print(respone.content) # body的二进制内容 (图片,视频) print(respone.status_code) # 响应状态码 print(respone.headers) # 响应头 print(respone.cookies) # 把响应的cookie转成了cookiejar的对象 print(respone.cookies.get_dict()) # 把cookiejar的对象转成字典 print(respone.cookies.items()) # key和value print(respone.url) # 请求的地址 print(respone.history) # 请求历史,重定向,才有数据,列表 print(respone.encoding) # 响应的编码格式 response.iter_content() #循环它,如果是视频,一点一点保存 解析json(http请求返回的数据是json格式): res.text是json字符串,取值不好取,需要json.loads(res.text)转成字典,再取值 直接res.json()转成json后的字典形式 import requests res = requests.post('http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword', data={ 'cname': '', 'pid': '', 'keyword': '上海', 'pageIndex': 1, 'pageSize': 10, }) # print(res.text) print(type(res.json())) 7.编码问题 url编码问题 把中文用url编码,把url编码解成中文 # https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3 from urllib import parse # 把中文用url编码, res=parse.quote('美女') print(res) # 把url编码解成中文 res=parse.unquote('%E7%BE%8E%E5%A5%B3') print(res) 网站编码,不是utf-8,使用res.text默认用utf-8转,可能出乱码 import requests res=requests.get('') # res.encoding='GBK' res.encoding=res.apparent_encoding print(res.text) 8.获取二进制数据 视频、图片需要保存二进制 import requests res=requests.get('https://img.lianzhixiu.com/uploads/allimg/202001/9999/a7b0199df8.jpg') with open('致命诱惑2.png','wb') as f: # f.write(res.content) for line in res.iter_content(1024): f.write(line) 9.request.session的使用 import requests session = requests.session() # 可以帮咱们保持cookie,以后不用手动携带 header = { 'Referer': 'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' } res = session.post('http://www.aa7a.cn/user.php', headers=header, data={ 'username': 'xxx@qq.com', 'password': 'xxx', 'captcha': 'fmd8', 'remember': 1, 'ref': 'http://www.aa7a.cn/', 'act': 'act_login', }) # 获取到cookie,登陆过后的cookie # cookie=res.cookies # print(cookie) # CookieJar res1 = session.get('http://www.aa7a.cn/', headers=header) print('xxx@qq.com' in res1.text) 补充: 什么是正向代理,什么是反向代理? 正向代理,隐藏客户端 *软件 反向代理,隐藏服务器 nginx 是一个反向代理服务器 正向代理---->买票的黄牛 反向代理---->租房的代理 总结: 1 爬虫介绍 模拟发送http请求---->获取到数据(html,json,图片,视频)---->数据清洗---->入库 2 请求库:requests模块 跟其他服务交互,使用requests模块 postman:完全自己写,使用requests写 3 发送get请求 4 发送get请求,地址中带参数 直接拼在路径中 params参数传入,字典 url编码和解码:中文编成url的编码形式 5 发送get请求,携带请求头 headers参数 user-agent:客户端类型 referer:上一个地址 6 发送请求,携带cookie 请求头 以参数形式携带 7 发送post请求 地址中带数据:params参数传入 请求头中带:headers 请求体中:data={},json={} 8 Respons对象属性,参数 text:响应的body体,转成了字符串 content:响应体的二进制(图片,视频) iter_content:图片,视频,循环保存 编码 cookies:一旦登录成功,这个cookies就是认证后的cookies json() :把返回的json格式字符串直接转成字典形式 9 编码问题 10 request.session的使用 ———————————————— 版权声明:本文为CSDN博主「不 再 熬 夜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/BLee_0123/article/details/131427517
-
线程在python当中是很有用,特别是在其他的编程语言当中,但是现代python开发者通常会因为几个原因避免使用它们,我们将会看到,还有其他并发编程方式正在吸引着python开发者的注意力,让我们在讨论这些话题之前先来看看线程中的一些陷阱。 共享内容。线程最主要的问题同时也是其最主要的优势,线程可以访问所有内存,也就是程序中的所有变量,这很容易导致程序状态的前后矛盾。你有没有进过一个房间,该房间有俩个开关可以控制一盏灯,这时有俩个人同事开灯会如何?每个人都语气自己会点亮这盏灯,但是最终的结果却违背了他们的预期,现在想象如果这俩个线程在银行账户之间进行转账。或者控制车辆的导航系统,后果将会怎么样?线程编程中对这一问题的解决方案是让共享变量的读、写代码实现“同步”访问。有几种不同的方式可以实现这一点,但是为了关注更Pythonic的方式,我们不去讨论它们。步的解决方案是可行的,但我们非常容易忘记使用。更糟的是,由于同步所导致的错误通常很难追踪(因为不同线程的执行顺序是不确定的),因此我们很难轻易重现错误。通常,最安全的做法是强迫线程之间的沟通使用一些已经正确使用了锁的轻量数据结构。python是供的queue.Queue 类就是其中的一种,它的功能和我们下面将要讨论的 Mitiprocessing.Queue相似。 在某些情况下,这些缺点有可能会超过共享内存所带来的速度优势。如果多个线程需委访问一个很大的数据结构,共享内存可以保证这一访问过程非常快速。然而,这一优势通常会由于Python线不同CPU上同时运行被消。这就带来了线程的第二个问题。 全局解释器锁 。为了有效地管理内存、进行垃圾回收以及在库中调用机器码,Python拥有一个名为全 oin()方法). 局解释器锁(GIL)的工具。它是无法被关闭的,这意味着线程在其他语言中所擅长的并 倍的提速正好 行处理在Python中是无用的。GIL的主要作用是阻止任何两个线程在同一时间运行(即便 它们有任务需要完成)。在这里,“有任务”意味着使用CPU,因此不同的线程访问磁盘或网络是完全可以的。一旦有线程等待,GIL 就会释放。 GIL的反对意见很多,大多数人不理解它是什么,或者它给Python带来的好处。如果 为几个原因 我们的语言没有这一限制当然很好,但是Python语言开发者决定,至少对于目前来说,它 的注意力。 所带来的价值超过了其产生的代价。它让语言实现起来更加容易开发和维护,而且在Python最初开发出来的单核处理器时代,实际上它使解释器运行得更快了。不过,GIL最终果是限制了线程所带来的优势,却没有缓解其消耗。
-
一、项目需求分析及拆解项目案例在写代码之前做需求分析,明白写什么,清晰的判断出来写的对不对,不然就白忙活了。首先需要梳理需求,根据第一篇文章写的。主要需求:当pytest执行结束之后,自动将结果发送到钉钉、微信、飞鼠、email等。不能指着一句话写代码,首先要对需求进行梳理,需要不断的抛出问题,结果包含什么?比如:希望pytest的结果包含什么呢?结合实际业务需求:测试开始时间(必有)测试结束时间测试执行时长测试用例总数量测试用例成功的数量测试用例失败的数量测试用例通过率测试报告地址等等 结合团队、环境根据实际开发。发送到“哪里”?根据实际情况发送到微信、钉钉、也可以扩展的比如说发展到推特、微博之类的。思考需求内容,是不同的场景,比如说:给钉钉发送消息呢?首先需要注册个钉钉号-钉钉号加自己号好友-通过消息对话框发送消息。另外方案:可以通过钉钉的群来发送,适用于发送给多人。 实现具体化。微信也是如此:个人、群、公众号。来了解发送到什么地方?怎么去发送?需要加好友、在手机或电脑发送好友消息。群的话不需要加好友用群的机器人发消息、通过接口发送消息。公众号也许要调用接口,前提是必须关注公众号才会发送内容。EMAIL通过SMTP服务器发送右键即可。什么时候发送?每次测试结束还是有用例失败?写代码之前分析需求,找产品经理确认需求再去做。比如说选择刚开始的:测试开始时间、测试执行时长、测试用例总数量、测试用例成功的数量、测试用例失败的数量、测试用例通过率。发送到群当中,使用机器人方式发送,选择而每次测试结束后发。二、编码思路编写伪代码,将需求思路捋一遍,保证代码正确。Pytest在运行时会调用很多hook,那我们需要哪些呢?根据分析来确定hook。比如:测试开始时自动执行,记录开始时间。测试结束时自动执行,记录结束时间,计算执行时长,发送结果。怎么去知道有多少个测试用例呢?需要hook,再收集完测试用例之后自动执行,记录总的用例数量。每一个用例执行结束之后自动执行,记录当前用例的结果。发送到什么地方需要用API,如果说发送到微信,只能用企业微信了,如果说发送到钉钉、飞书是提供相关接口的。以微信为例,在群当中添加机器人的名字后会出现接口和接口的说明。如图:补充:通过EMAIL的SMTP协议来发送,所以我们需要SMTP的服务器、账号、链接代码实现。先写测试用例在写代码,比如说记录时间,怎么确定是记录到了呢?需要测试用hook确实得到了相关结果,保证产品交互。但是不可能写完所有代码后再去测试,这就缺少了全局观,不知道代码细节所以更偏向黑盒测试,但测试开发更偏向于白盒测试,所以用例需要在写代码之前或交互之前完成,先设计测试用例,分为俩个测试:单元测试:测试开始时间、执行时长,是否准确。用例执行结果,是否准确。用例数量,是否准确。用例通过率,是否准确。API或SMTP,是否可用。集成测试(满足整体需求):测试结束时,在微信群中,收到结果通知。通过单元测试判断做的某一些事情是否准确,通过集成测试来判断单元测试是否都完成并准确后才用到的,验证整个项目是否满足需求。三、编码从单元测试角度分析来编码,在之前plugin.py中已经完成了第一步,为了能够测试它需要写一个测试用例,如图:设置代码的相应时长为2.5s,所以再2.5之后会完用例执行。在plugin中编写date时间,自动为它生成一个执行耗时,放到执行之后,打印出来时间。如图: 单元测试,通过断言来判断花费时间,是否正确。如图: 运行pytest即可查看,是否正确,如果错了就会报错。验证了起始时间、结束时间、用例执行时间是准确的。用例执行结果,如果只有一个用例可能会报错,可以多写几个用例,正常来说是三个用例,俩个通过一个失败。如图: 检查用例数量是否正确,通过断言,assert来判断,数量是否等于3.,在收集完之后在判断,首先需要导入putest,进入之后找到所有hook,可以通过左下角的类和变量来快速找到参数,收集相关的并翻译,插件其实也可以对项目进行筛选和排序。在所有用例完成之后调用钩子,来证明所有用例收集之后结束。写钩子中的session是空函数,名字、参数、结果,参数是session包含了很多信息用例之类的,收集到的用例在什么地方呢?用例在完成之后执行,包含了全部的用例。如图:如果涉及到了长周期的项目,怎么知道完成的定位?用例就是代表了要做的事情,数量就代表了工作的进度,用例的执行结果?通过断言来判断。如图:执行的过程都会报错,不会让你把工作疏忽掉,其实也就间接的定位了工作进程,有用例就可以提醒什么地方没有做到位。这叫做测试驱动开发、开发进度、质量,下一步重点都是测试用例来把握。每一个用例执行结束之后自动执行,记录当前结果。在钩子中,名字、参数、返回值比较重要,没有返回值就看其余的。当有很多钩子选择时选择参数才是对的,logreport就是结果,找到runtest开头,report的,对钩子可以先翻译,有个基本的了解。如图: 三个用例为什么这么多结果,其实是每个用例分了三个部分,setup、调用、teardown阶段、其实在call就是调用阶段就可以知道是通过还是失败。加一个判断,如图: 做一个数据的记录,记录多少个失败多少个成功,修改断言处的pass为passed,fail为failed,并统计一下一共有多少个数量,在date当中设一个初始值,当某一个用例出现结果之后呢就会修改当中的相关的用例类型的数量 就是说本次用例如果通过就让结果统计的数据+1。,没有前面的报错说明结果是ok的,单元测试到此就已经测试通过了。测试通过率就不好写断言了,通过date来计算值。计算百分比也可以通过GPT来算如图: 修改2f后加入%,上述代码66.66改为66.67.单元测试中的接口API地址,在测试中设置url请求地址,查看后是发送json的请求,所以首先导入requests,并在pdm后安装requests不需要加-d。可以在项目的配置文件中查到requests的版本号是多少,确定了确实存在这个东西。这样在安装时候才能自动下载安装。如图:根据手册中的内容是发送post请求,比如说requests.post中,用普通文本的类型来实现,可以先测试下hello,world如图:结果就是群里面发送了相关信息,证明了API是可用的。机器人说明当中还可以艾特某人、markdown格式。里面可能带字体颜色、语法。如图: 也可以自己建一个mkdown,md文件来写内容,比如说pytest自动化测试结果,需要测试时间、用例数量、执行时长、测试通过、测试失败、测试通过率、测试报告地址:http://baidu.com 如图: 也可以通过加一个标签或mkdown的形式来体现测试失败的样子。颜色自己改如图: 将写好的代码放到.py测试文件中,并将content内容放到下方的content。如图: 集成测试。我们执行pytest,客户可以直接收到结果,集成不太方便自动化,将接口请求代码和它进行集成。将.py的代码复制到plugin中去,并把import放到data上面去,将测试时间放到下方的测试时间中去,加一个f用一个花括号来替代并把所需要发送的内容依次替代即可。注意百分号如果加在双引号里面则后续不用修改,如果百分号加在外面,后面的也需要加百分号并加在外面。如图: 补充:在这里可以去掉换行,否在影响发送效果,执行时间可以进一步的优化。可以删掉s,优化毫秒。如图:先pdm check 优化代码、检查代码质量赶快commit提交!!!备注随便写,可以获取必要数据并发送到企业微信中去。如果需要严格的验证可以pdm build打包出来,下方会出现安装包,使用全新的环境来安装安装包,来模拟全新的使用和环境的电脑。如图:报错问题是因为版本号:可以pip install 后再卸载这次运行就可以啦~完美 撒花 结束!
-
下载直接去anaconda官网下载安装文件即可,具体网站自行搜索。官网提供linux版本,windows版本,mac版本。同时提供Anaconda完整版和miniconda最小版(无软件界面的,仅支持命令行执行),新手推荐使用Anaconda版,熟悉之后推荐改用miniconda版,占用存储空间小,使用起来感受一样。安装linux环境bash Anaconda3-2019.07-Linux-x86_64.sh#yes+回车#然后重启terminalwindow环境直接双击安装exe文件,然后根据安装向导进行安装升级升级Anaconda需要先升级condaconda update conda #基本升级 conda update anaconda #大的升级 conda update anaconda-navigator //update最新版本的anaconda-navigator 卸载Anaconda软件由于Anaconda的安装文件都包含在一个目录中,所以直接将该目录删除即可windows计算机控制面板->程序与应用->卸载 //windows或者找到C:\ProgramData\Anaconda3\Uninstall-Anaconda3.exe执行卸载linuxrm -rf anaconda最后,建议清理下.bashrc中的Anaconda路径。conda环境使用基本命令conda update -n base conda #update最新版本的conda conda update --all #update最新版本的conda conda create -n xxxx python=3.5 #创建python3.5的xxxx虚拟环境 conda activate xxxx #开启xxxx环境 conda deactivate #关闭环境 conda env list #显示所有的虚拟环境 conda info --envs #显示所有的虚拟环境查看指定包可安装版本信息命令查看tensorflow各个版本:(查看会发现有一大堆TensorFlow源,但是不能随便选,选择可以用查找命令定位)conda search -h #查看search使用帮助信息conda search tensorflow查看指定包可安装版本信息命令anaconda show <USER/PACKAGE> 查看指定anaconda/tensorflow版本信息conda show tensorflow 输出结果会提供一个下载地址,使用下面命令就可指定安装1.8.0版本tensorflowconda install --channel cid:link_7 tensorflow=1.8.0更新,卸载安装包:conda list #查看已经安装的文件包 conda list -n xxx #指定查看xxx虚拟环境下安装的package conda update xxx #更新xxx文件包 conda uninstall xxx #卸载xxx文件包删除虚拟环境conda remove -n xxxx --all //创建xxxx虚拟环境清理(conda瘦身)conda clean就可以轻松搞定!第一步:通过conda clean -p来删除一些没用的包,这个命令会检查哪些包没有在包缓存中被硬依赖到其他地方,并删除它们。第二步:通过conda clean -t可以将删除conda保存下来的tar包。conda clean -p //删除没有用的包 conda clean -t //删除tar包 conda clean -y --all //删除所有的安装包及cache复制/重命名/删除env环境Conda是没有重命名环境的功能的, 要实现这个基本需求, 只能通过愚蠢的克隆-删除的过程。 切记不要直接mv移动环境的文件夹来重命名, 会导致一系列无法想象的错误的发生!conda create --name newname --clone oldname //克隆oldname环境为newname环境conda remove --name oldname --all//彻底删除旧环境注意:必须在base环境下进行以上操作,否则会出现各种莫名的问题。conda自动开启/关闭激活conda activate #默认激活base环境 conda activate xxx #激活xxx环境 conda deactivate #关闭当前环境 conda config --set auto_activate_base false #关闭自动激活状态 conda config --set auto_activate_base true #关闭自动激活状态Conda 安装本地包有时conda或pip源下载速度太慢,install a过程中会中断连接导致压缩包下载不全, 此时,我们可以用浏览器等工具先下载指定包再用conda或pip进行本地安装#pip 安装本地包 pip install ~/Downloads/a.whl #conda 安装本地包 conda install --use-local ~/Downloads/a.tar.bz2解决conda/pip install 下载速度慢conda数据源管理#显示目前conda的数据源有哪些 conda config --show channels #添加数据源:例如, 添加清华anaconda镜像: conda config --add channels cid:link_0 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes #删除数据源 conda config --remove channels cid:link_0pip数据源管理#显示目前pip的数据源有哪些 pip config list pip config list --[user|global] # 列出用户|全局的设置 pip config get global.index-url # 得到这key对应的value如:cid:link_4添加pip config set key value #添加数据源:例如, 添加USTC中科大的源: pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/web/simple #添加全局使用该数据源 pip config set global.trusted-host https://mirrors.ustc.edu.cn/pypi/web/simple删除pip config unset key例如conda config --remove channelscid:link_0搜索pip search flask #搜素flask安装包升级pippip install pip -U阿里云 cid:link_6中国科技大学 cid:link_3豆瓣(douban) cid:link_8清华大学 cid:link_2中国科学技术大学 cid:link_5pip安装包管理pip list #列出当前缓存的包 pip purge #清除缓存 pip remove #删除对应的缓存 pip help #帮助 pip install xxx #安装xxx包 pip install xxx.whl #安装xxx.whl本地包 pip install -r requirements.txt #批量安装 pip uninstall xxx #删除xxx包 pip show xxx #展示指定的已安装的xxx包 pip check xxx #检查xxx包的依赖是否合适转载自cid:link_1
-
一、创建一个新的插件:项目为单位的管理模式直接新建项目步骤:1:创建新的项目2:创建虚拟环境 venv3:安装pdm 自行安装4:使用我们的pdm来初始化项目 新建项目指定项目的位置,然后我们创建pytest插件约定一定要pytest-开头,创建一个结果通知插件 自动将整个pytest测试结果通过钉钉、飞书方式发送出去名字建立: 输入pdm init 输入y安装插件 后默认即可回车就可以了。如图: 手动创建目录src存放项目源码和tests存放测试用例,写的插件、项目都要有对应的单元测试用例,创建pythonpackage包 再python当中你的包名不可以出现+-号,名为pytest_result_sender。Pyproject.toml是项目源码,项目源码当中介绍 插件名字文本号或作者以及依赖还可以添加插件的入口点并指定源码再src中如图:项目创建就ok了。2:编写代码:举个简单例子,新建python文件创建插件文件再plugin.py中写hook,比如首先在,From datetime import datetime是生成当前实践Def pytest_configure():#会在配置加载完毕之后执行,也就是再测试用例前面执行Print(f”{datetime.now()}”pytest开始执行)Def pytest_unconfigure():Print(f”{datetime.now()}”pytest结束执行)再所由用例之前执行这个代码如图实现最终效果:二、测开平台之企业级项目开发实战篇1.建立git仓库跟踪代码更新进行版本控制2.使用black+iosrt的进行代码质量控制3.项目需求分析梳理及拆解设计测试用例4.测试驱动开发完成mvp最小化可行产品1.使用git进行代码版本的控制使用git不仅仅是把他存起来,托管,也是通过git方式来跟踪代码变化,防止代码写错或bug、删掉代码如何找回呢?都是通过该控制工具实现。使用方法:1:初始化仓库Git init项目目录在什么地方就在这个地方执行命令即可。仓库不是源码的一部分而是将源码放到仓库中,从代码变化到仓库变化。会将仓库内容保存到git中,使用俩种方式实现内容分割,.git代表隐藏、也可以通过右键查看是否为隐藏文件。如果仓库已经创建再去执行也可以,如图所示:2.将代码放到仓库当中安装git时可以右键git gui 通过使用git自带的界面。如图所示。来对内容进行控制,初始化项目之后也可以在上面的菜单栏当中点击git的按钮里面也有很多东西来修改。删除.git文件后会发现无法使用git命令。如图所示:1)Git gui页面介绍画红色圈圈地方是没有保存到仓库文件,但是已经提交了。下方的四个按钮第一个是扫描,第二个是存储,第三个是签名,第四个是提交,第五个是push。推到远程仓库当中。可以每个按钮按一遍就知道怎么操作了,可以通过提交历史来查看第一次代码的提交。注意:忽略配置是不关心不重要不希望加到代码仓库中比如说:pycharm编译器里面东西,预编译文件等。让我们的git忽略掉它,对它视而不见有俩种方法:第一种就是将需要的文件选中到代码仓库,但是有点笨,而且不好拿捏哪个是忽略的配置第二种是配置文件在pycharm中在pycharm根目录中创建一个git忽略文件,如图所示。里面对编译文件、扩展文件、虚拟环境,写到这个文件中的内容是不要的,写完后在ui界面重新扫描下会发现文件就少了很多,如图所示。只剩下了gt的忽略文件,项目配置文件、源码等等。忽略了:ide、python的预编译文件就是pyc解位的文件、各种临时文件、包括还有我们的打包编译文件等等。这些都可以直接拿来用就不用自己写了。如何查看自己删除掉的代码呢?可以将上方写的plugin.py下方的代码库删掉后点击下方的log日志查看。如图所示。就可以看到上面的文件下写着在plugin.py下删除了右侧的代码。然后再ui界面来备注下:清空掉了代码内容 点击commit提交这地方就是清空掉了,这时候便是入库存储起来了,后续文件的修改需求也可以这么做,如果有一天后悔了这么改可以回滚回来吗?是可以的,不需要备份!怎么找回之前删除的代码呢?比如说要找plugn的文件可以选中文件后再编辑页右键选中git再选中show diff 显示版本之间的差异,下方可以选中历史,比如说再三分钟或俩分钟之前是什么样的,可以回滚操作,选中要回滚的时间,右键选中showdiff,修改上方的行参数来回退到之前版本,或再git中选中resethead如图所示。将版本号再右下方带有数字放到head中,选择head方式来reser重置,代码就回来了。 2)回退版本 Reset –head 再不同版本之间随便跳跃比如将来代码中出现bug,不知道怎么修改可以回退到上一个没有bug的版本,保证系统正常,主要是来记录代码和遇到突发状况可 以实现版本回退,多个版本之间可以比较版本之间的差异。用git来实现代码的控制,为了确保代码有备份能控制可回退:一定要及时的commit!如果没有commit代码而 是直接reset代码就会丢失。 注意:一定要及时commit!!!2.使用black+iosrt代码的质量控制和之前的代码版本控制,改了什么怎么样改回来,这里更注重代码不能随便的写,由于每个人可以写出不同的风格所以要求质量控制,通过使用三件套black、isort、flake8来进行代码的质量控制,保证每个人的代码质量、风格等接近。Pdm是全项目的管理不仅仅用到安装使用工具时首先安装依赖Pdm add 要安装的东西即可 和pytest同理 但是不能这样去做,我们安装了以来但是使用这些的人需要安装这样工具吗?不需要。我们写插件要用到这种东西但是不能强加给使用框架或插件的人,应该怎么办?在开发依赖后加-dPdm add black iosrt flake8 -dPdm add pytest 叫运行依赖什么叫运行依赖?运行这个软件或系统就要安装pytest,开发依赖顾名思义就是在开发中需要而不是在终端用户中用到,所以不会安装。安装如图: 三种工具之间的角色:Black::不妥协的代码格式化,让每一个开发的代码形成统一的风格标准。在下方输入 black 文件名字回车就会发现代码被格式化了,如图所示。 Iosrt:对import语句进行排序 用法同理 black。导入的规则: 导入系统内置模块、第三方模块随后是自己写的模块。Flake8:代码质量分析 主要是检测代码中潜在的bug,怎么解决bug,分析什么变量、导入什么模块、在什么地方使用模块、使用的方式对不对合不合理进行分析。用法同理black。上面三个工具对代码进行修改和质量检查避免有很多坑,对多个文件怎么使用工具呢?配置脚手架让它自动执行,在project.toml中去写,代码如下: 创建check会自动调用这三个工具,并创建flake文件让它在检查时可以将不必要文件进行排除。 这时候在命令行中敲入:pdm check 就会自动的检查所有的文件,如图所示。 提示的地方可能是代码的错误问题,需要自行修改在修改完后再次执行会发现没有任何错误提示,就是搞定了。代码项目配置好后可以保存项目修改,点击git后点击commit。在文件下方也可以输入备注信息来区分,可以通过下方git查看保存信息。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签