IBM-数据工程-III-笔记-全-
IBM 数据工程 III 笔记(全)
001:Python数据工程项目课程介绍

在本课程中,我们将通过一个真实世界的数据工程项目,学习如何使用Python进行数据工程的核心操作。课程将涵盖数据提取、转换、加载(ETL)的全过程,并指导你构建一个完整的ETL管道。

数据工程师是任何组织数据战略和规划的前线人员。数据工程任务,包括从源中提取数据、将其转换为所需格式以及加载以供进一步使用,是整个数据科学行业所依赖的基础操作。这也是数据工程师职位成为当今全球最受欢迎职位之一的主要原因。
在这个基于项目的课程中,你将扮演专业数据工程师的角色,处理真实世界的数据。你将使用Python,通过网络爬虫技术直接从网站获取所需数据,根据要求转换数据,并将其保存为本地文件和数据库中的表。你还将使用Python对数据表运行基本查询。
🎯 课程目标与适用人群
本课程面向具备基本编程知识、对Python有初步了解,并有意将其用于数据工程应用的任何人。
完成本课程后,你将能够:
- 通过读取数据文件、网络爬虫和使用API,从多个来源提取数据。
- 按要求转换数据。
- 将处理后的数据加载到所需格式或数据库中。
- 为访问和处理来自公共网站的数据,创建一个完整的ETL管道。
- 创建Python模块,运行单元测试并打包应用程序。

📚 课程模块概览
模块一:ETL与数据获取基础
上一节我们介绍了课程的整体目标,本节中我们来看看第一个模块的内容。
在模块一中,你将学习提取、转换和加载(ETL)操作的基础知识。你将使用网络爬虫技术和API从网页中提取所需信息。你还将学习使用Python访问数据库,并将处理后的信息作为表保存在数据库中。
以下是本模块的核心学习点:
- ETL操作基础:理解数据工程的提取(Extract)、转换(Transform)、加载(Load) 流程。
- 数据获取技术:掌握使用
requests、BeautifulSoup等库进行网络爬虫,以及使用requests库调用API。 - 数据库交互:学习使用
sqlite3或SQLAlchemy等库连接数据库并执行操作。
模块二:构建ETL管道实战
在掌握了基础知识后,模块二将引导你将所学知识应用于实践。
在模块二中,你将运用前一模块的知识,开发一个功能性的ETL管道,用于获取和处理公共领域网站的数据。通过一个练习项目和一个计分项目,你将展示从不同网页链接为数据创建ETL管道的熟练程度。你需要提交项目作业供同伴互评。


以下是本模块的核心任务:
- 项目实践:完成一个完整的ETL项目,代码结构可能如下所示:
# 示例:简化的ETL流程框架 def extract_data(url): # 从URL提取数据 pass def transform_data(raw_data): # 清洗和转换数据 pass def load_data(clean_data, db_connection): # 将数据加载到数据库 pass # 主ETL管道 data = extract_data("http://example.com/data") processed_data = transform_data(data) load_data(processed_data, database) - 技能评估:在计分项目中,综合运用爬虫、数据清洗和数据库操作技能。
模块三:代码开发与最佳实践
构建了可用的管道后,我们还需要确保代码的质量和可维护性。这就是模块三的重点。

在模块三中,你将使用Python创建模块、运行单元测试并打包应用程序。你还将学习Python的理想编码实践并运行静态代码分析。


以下是本模块的核心学习点:
- 模块化开发:将代码组织成可重用的模块。
- 质量保证:使用
unittest或pytest框架编写和运行单元测试。 - 应用打包:学习使用
setuptools打包Python应用。 - 代码规范:遵循PEP 8等编码规范,并使用工具(如
pylint或flake8)进行静态代码分析。
💡 学习建议
课程内容非常丰富。为了从中获得最大收益,请确保观看每个视频,通过每个测验检查学习成果,并完成所有动手实验。如果你在任何课程材料上遇到困难,请随时在讨论论坛中联系我们。

🏁 总结
本节课中,我们一起学习了《Python数据工程项目》课程的总体介绍。我们明确了数据工程师的角色和ETL流程的重要性,概述了三个核心模块的学习路径:从ETL基础与数据获取,到实战构建管道,再到代码开发与最佳实践。最后,我们列出了完成本课程后你将掌握的关键技能,并提供了成功的学习建议。


现在,你已经准备好开启这段实践之旅,亲手构建你的第一个数据工程管道了。祝你学习愉快!😊
002:云端IDE工作演示 🚀
在本课程中,我们将学习如何使用IBM Skills Network团队提供的云端集成开发环境。这是一个无需在个人设备上安装任何软件,即可在浏览器中编写、运行、调试和执行代码的编程学习环境。
云端IDE界面概览 🖥️
打开云端IDE后,界面会显示两个主要窗格。

左侧窗格被称为教学窗格,用于显示完成项目所需遵循的指令。
右侧窗格则是一个编程界面,您可以在此编写和执行代码。请注意,此界面与流行的代码管理IDE——VS Code非常相似。
您可以调整教学窗格和代码窗格的大小。例如,通过拖动其边缘向左来缩小教学窗格,或向右拖动来扩大它。
您还可以根据个人偏好修改字体和字号。
如果教学窗格包含多个页面,您会看到“下一页”和“上一页”按钮,用于在页面间导航。您也可以预览教学页面。
注意教学窗格左上角的“目录”按钮,使用它可以在不同指令章节间导航。
使用AI教学助手聊天机器人 🤖
接下来,我们看看云端IDE上可用的AI教学助手聊天机器人。
IBM Skills Network团队提供了一个名为“TI”的AI教学助手聊天机器人,它能帮助您使用实验环境完成编码作业。TI的图标位于教学窗格的左侧。
要访问聊天机器人,只需点击该图标。

让我们尝试提问,例如:“请给我一个简单的Python代码。” 如您所见,代码会显示出来。您可以复制或执行这段代码。
编程界面详解 💻
现在,让我们深入了解IDE的编程界面。
编程界面包含多个组件,但您将频繁使用的两个标签页是:编辑器标签页(用于编写代码)和终端标签页(用于执行代码)。
在编程窗格中,还有一个Skills Network工具箱,它使您能够使用各种数据库管理环境、大数据工具、云工具、嵌入式AI库,并启动您构建的应用程序。
在开始编写代码之前,您需要在这个云端环境中安装所需的Python库或包。这个任务需要在终端标签页中完成。
要打开一个新终端,点击“终端”菜单,然后选择“新建终端”。为了演示,让我们从教学窗格复制代码块,并将其粘贴到终端中。

然后,按回车键执行命令。请注意,numpy库已成功安装。现在,您可以将这个库导入到您的代码中了。
创建并运行Python程序 🐍

现在,让我们在编程窗格中创建一个基础的Python程序。
点击“文件”,然后选择“新建文件”。新文件将在编辑器标签页中打开。在开始添加代码前保存文件是一个最佳实践。
由于我们正在编写Python代码,请将文件保存为以 .py 为扩展名的文件。从文件菜单中,点击“保存”或使用快捷键 Ctrl+S。当提示时,提供文件名。在此示例中,我们将文件保存为 hello.py。

下一步是添加代码。您可以在编辑器标签页中手动输入代码,或者如果教学窗格中有可用代码,可以将其复制并粘贴到您的文件中。
为了本次演示,让我们从教学窗格复制代码并粘贴到文件中。别忘了保存文件。
是时候执行代码了。让我们导航回终端标签页。
确保您位于存储程序文件的文件夹中。您可以通过输入 python3 后跟文件名来执行文件。对于此示例,命令是 python3 hello.py。

请注意,输出已显示且没有任何错误。
课程总结 📝
本次云端IDE演示到此结束。总结一下,云端IDE是一个类似于VS Code的编程环境,由IBM Skills Network提供,旨在用于学习和培养实践技能。
云端IDE有两个窗格:教学窗格和编程窗格。您可以使用教学窗格上的“目录”按钮在不同教学页面间导航。
编程窗格提供了用于编写代码的编辑器标签页和用于执行代码的终端标签页。您需要通过终端安装所需的库。

在实验过程中的任何时候,您都可以从教学窗格复制代码块,并将其粘贴到编辑器或终端标签页中。
003:提取、转换、加载(ETL)🧩



在本节课中,我们将学习提取、转换、加载(ETL) 过程。我们将定义ETL流程,解释其功能的正确顺序,并编写一个简单的ETL程序。

你是否曾想过,数据是如何从多个来源收集并合并成单一信息源的?这种数据收集方式称为批处理。今天,我们将探讨一种名为提取、转换、加载(ETL) 的批处理类型。
ETL正如其名所示。它是从多个来源和格式中提取大量数据,将其转换为特定格式,然后加载到数据库或目标文件中的过程。让我们用以下框图来表示ETL管道。

例如,假设你是一家初创公司的所有者,该公司开发了一个人工智能,利用身高和体重预测某人是否有患糖尿病的风险。你的部分数据是CSV格式,另一部分数据是JSON文件。你需要将所有数据提取到一个文件中,以便人工智能读取。你的数据是英制单位,但人工智能使用公制单位,因此你必须转换它。人工智能只读取一个大型CSV文件中的数据,因此你需要将数据加载为CSV格式。





让我们用Python实现以下ETL过程。首先,我们将通过一些简单示例查看提取步骤。但在讨论提取函数之前,让我们先讨论其组成部分函数。
以下是glob模块中的glob函数。输入是文件扩展名,输出是具有该特定扩展名的文件列表。
考虑JSON和CSV文件列表。输入是glob文件扩展名,前面带有星号和点号。输出是CSV文件列表,我们可以对JSON文件执行相同操作。
我们可以编写一个函数来提取包含姓名、身高和体重的CSV文件。输入是CSV文件的文件名,结果是一个数据框。我们可以对JSON格式执行相同操作。输入是JSON文件的文件名,输出是一个数据框。请查看实验部分以获取更多示例。


🔍 提取函数




提取函数将从多个来源批量提取大量数据。我们创建一个空数据框。
extracted_data = pd.DataFrame(columns=['name','height','weight'])


结果是一个分配了列名的空数据框。


让我们看看提取CSV文件的过程。



我们首先添加一个循环来查找所有CSV文件。这可以通过添加glob函数轻松实现。添加此函数后,它将查找并加载所有CSV文件名。在循环的每次迭代中,CSV文件被追加到数据框中。第一次迭代将被追加,然后是第二次迭代,从而生成提取的数据列表。我们稍后将回顾参数ignore_index=True。
这段代码将JSON文件追加到数据框中。让我们看看参数ignore_index如何设置索引顺序。每列都按追加到数据框的顺序设置索引。我们将查看输出提取的数据。
如果我们没有将参数ignore_index设置为True,那么数据框extracted_data的索引将与原始文件的行号相同。如果我们确实将ignore_index设置为True,那么每行的顺序将与行追加到数据框的顺序相同。




🔄 转换函数
既然我们已经收集了数据,流程的下一步就是转换它。此函数将列height从英寸转换为毫米,列pounds转换为千克,并在变量data中返回输出。让我们仔细看看。
在输入数据框中,列height以英尺为单位。我们对列应用以下操作,将其转换为米并四舍五入到两位小数。




data['height'] = round(data['height'] * 0.0254, 2)
结果数据框列height现在以米为单位,我们可以对体重执行相同操作。

📤 加载和日志记录
现在我们已经收集并定义了数据,是时候将其加载到目标文件中了。在这种情况下,我们将pandas数据框保存为CSV文件。


data.to_csv(targetfile, index=False)
我们已经完成了从多个来源提取、转换和加载数据,并将其最终化为一个目标文件的过程。在完成任务之前,我们需要创建一个日志条目。为此,我们将创建一个日志记录函数。
首先创建一个名为timestamp_format的变量,它确定时间和日期的格式。接下来是now变量,它将通过调用datetime捕获当前时间。添加此内容后,导入了datetime以使其正常工作。然后,我们通过打开文件并将信息写入文件来汇总这些信息,加上'a'后,所有写入的数据都将追加到现有信息中。
通过创建这种类型的条目,我们能够为流程的每个部分附加时间戳,记录其开始和完成的时间。



🚀 运行ETL流程


现在我们已经定义了在选定数据上运行ETL流程所需的所有代码,最后需要做的就是调用所有函数。我们首先调用extract_data函数。

extracted_data = extract()

从此步骤接收的数据将转移到转换数据的第二步。完成后,数据将加载到目标文件中。此外,请注意,在每一步之前和之后,都添加了开始和完成的日期和时间。



📝 总结


在本视频中,你学习了如何编写一个简单的提取函数、一个简单的转换函数、一个简单的加载函数以及一个简单的日志记录函数。请查看实验部分以获取更多信息。
004:可选网络抓取 🕸️


在本节课中,我们将学习网络抓取的基本概念和操作方法。通过本课,你将能够定义网络抓取,理解Beautiful Soup对象的作用,应用find_all方法,并实际完成一个网站的抓取任务。
概述 📋
网络抓取是一种自动从网站提取信息的过程。想象一下,如果你需要分析数百个数据点来找出运动队的最佳球员,手动从不同网站复制粘贴信息到电子表格不仅耗时,而且可能因为任务过于繁重而放弃。网络抓取可以在几分钟内自动完成这项工作。
开始之前:工具准备 🛠️




要开始网络抓取,我们只需要一些Python代码以及两个模块的帮助:requests和beautifulsoup4。



假设你需要从一个网页中找出国家篮球联赛球员的姓名和薪水。
首先,我们导入Beautiful Soup。我们可以将网页HTML作为字符串存储在变量中。为了解析文档,我们将其传递给Beautiful Soup构造函数,从而得到一个Beautiful Soup对象soup。这个对象将文档表示为嵌套的数据结构。
Beautiful Soup将HTML表示为一组树状对象,并提供了用于解析HTML的方法。
理解Beautiful Soup对象 🌳
我们将使用创建的Beautiful Soup对象soup来回顾其结构。




标签对象对应于原始文档中的HTML标签。例如,title标签。




考虑h3标签。如果存在多个相同名称的标签,默认会选择第一个具有该标签的元素。以“勒布朗·詹姆斯”为例,我们看到姓名被包裹在粗体属性<b>中。为了提取它,我们使用树状表示法。

变量tag_object位于此处。我们可以访问标签的子元素,或者沿着分支向下导航,如下所示:
tag_object.child




你可以通过使用parent属性向上导航树。变量tag_child位于此处,我们可以访问其父元素。这就是原始的标签对象。
我们还可以找到标签对象的兄弟节点。只需使用next_sibling属性。
我们可以找到sibling1的兄弟节点。只需使用next_sibling属性。
考虑tag_child对象。你可以像字典中的键值对一样访问属性名称和值,如下所示:




tag_child.attrs

你可以将内容作为可导航字符串返回。这类似于支持Beautiful Soup功能的Python字符串。
探索find_all方法 🔍
现在,让我们回顾find_all方法。这是一个过滤器。


你可以使用过滤器基于标签名称、属性、字符串文本或这些条件的组合进行过滤。




考虑一个披萨店列表。像之前一样,创建一个Beautiful Soup对象,但这次将其命名为table。

find_all方法会遍历标签的后代,并检索所有匹配过滤器的后代。将其应用于带有<tr>标签的表格。结果是一个Python可迭代对象,就像一个列表。
每个元素都是<tr>的标签对象。这对应于列表中的每一行,包括表头。
每个元素都是一个标签对象。以第一行为例,我们可以提取第一个表格单元格。我们还可以遍历每个表格单元格。
首先,我们通过变量row遍历列表table_rows。每个元素对应于表格中的一行。我们可以应用find_all方法来查找所有表格单元格。然后,我们可以为每一行遍历变量cells。在每次迭代中,变量cell对应于该特定行中表格的一个元素,我们继续遍历每个元素,并为每一行重复此过程。
应用Beautiful Soup抓取网页 🌐




为了抓取网页,我们还需要requests库。




第一步是导入所需的模块。使用requests库的get方法下载网页,输入是URL。使用text属性获取文本,并将其分配给变量page。然后,从变量page创建一个Beautiful Soup对象soup。这将允许你解析HTML页面,现在你可以开始抓取页面了。




查看实验部分以获取更多信息。
总结 📝



在本节课中,我们一起学习了网络抓取的基本概念和操作方法。我们了解了如何使用requests和beautifulsoup4库来下载和解析网页,掌握了Beautiful Soup对象的结构和find_all方法的应用,并初步实践了从网页中提取所需信息的过程。网络抓取是数据工程中一项强大的技能,能够高效地从网络资源中收集和整理数据。
005:Python数据工程项目课程 📚


第5部分:可选内容 - 使用Requests库进行REST API HTTP请求 🌐
在本节课中,我们将学习如何使用Python的Requests库来处理HTTP协议。我们将回顾这个用于处理HTTP协议的流行库,并概述GET请求和POST请求的基本概念和用法。
概述Requests模块


首先,我们来回顾Python中的Requests模块。这是几个可以处理HTTP协议的库之一,其他库还包括HTTPLib和URLLib。


Requests是一个Python库,可以让你轻松地发送HTTP/1.1请求。我们可以通过以下方式导入这个库:
import requests
你可以使用get方法向www.ibm.com发起一个GET请求。我们会得到一个响应对象r,它包含了关于请求的信息,比如请求的状态。
r = requests.get('https://www.ibm.com')
检查响应信息
我们可以使用status_code属性查看状态码,状态码200表示请求成功。



print(r.status_code) # 输出: 200


你可以查看请求头。由于GET请求没有请求体,所以请求体为None。


print(r.request.body) # 输出: None
你可以使用headers属性查看HTTP响应头。这会返回一个包含HTTP响应头的Python字典。
print(r.headers)

我们可以查看这个字典的值。例如,使用键date可以获取请求发送的日期。键content-type指示了响应数据的类型。
print(r.headers['date'])
print(r.headers['content-type'])


使用响应对象r,我们还可以检查编码。

print(r.encoding)
处理响应内容


由于内容类型是text/html,我们可以使用text属性来显示响应体中的HTML内容。我们可以查看前100个字符。

print(r.text[:100])
你也可以下载其他内容,更多细节请参阅实验部分。


使用GET方法进行查询

你可以使用GET方法来修改查询结果,例如从API检索数据。在实验中,我们将使用httpbin.org,这是一个简单的HTTP请求和响应服务。
我们像之前一样向服务器发送一个GET请求。我们有基础URL和路由。我们附加/get,这表示我们想要执行一个GET请求。


在GET请求之后,我们有查询字符串。这是统一资源定位符(URL)的一部分,它向Web服务器发送其他信息。查询字符串以一个问号开始,后面跟着一系列参数和值对。

以下是参数和值对的示例:
- 第一个参数名是
name,值是Joseph。 - 第二个参数名是
id,值是123。
每个参数和值对之间用等号分隔。一系列参数对之间用&符号分隔。


让我们在Python中完成一个示例:

url_get = 'http://httpbin.org/get'
payload = {'name': 'Joseph', 'id': '123'}
r = requests.get(url_get, params=payload)

我们有基础URL,并在末尾附加了/get。我们使用字典payload,其键是参数名,值是查询字符串的值。然后我们将字典payload传递给get函数的params参数。
我们可以打印出URL,查看其中的名称和值。


print(r.url) # 输出: http://httpbin.org/get?name=Joseph&id=123


由于信息是通过URL发送的,请求体的值为None。
print(r.request.body) # 输出: None
我们可以打印出状态码。


print(r.status_code) # 输出: 200
我们可以将响应视为文本查看。

print(r.text)


我们可以查看键content-type来了解内容类型。由于内容类型是JSON,我们使用json()方法格式化它,它会返回一个Python字典。
print(r.headers['content-type']) # 输出: application/json
data = r.json()
print(data['args']) # 输出: {'name': 'Joseph', 'id': '123'}
键args包含了查询字符串的名称和值。
理解POST请求
与GET请求类似,POST请求也用于向服务器发送数据。但POST请求将数据放在请求体中发送,而不是放在URL里。
为了在URL中发送POST请求,我们将路由改为/post。这个端点期望接收数据,这是一种配置HTTP请求以向服务器发送数据的便捷方式。
我们使用payload字典来发起POST请求,使用post函数。变量payload被传递给参数data。


url_post = 'http://httpbin.org/post'
payload = {'name': 'Joseph', 'id': '123'}
r_post = requests.post(url_post, data=payload)


比较GET和POST请求


比较GET和POST请求响应对象的url属性,我们看到POST请求的URL中没有名称和值对。



print("GET URL:", r.url) # 包含查询参数
print("POST URL:", r_post.url) # 不包含查询参数

我们可以比较POST和GET请求的请求体,我们看到只有POST请求有请求体。
print("GET request body:", r.request.body) # 输出: None
print("POST request body:", r_post.request.body) # 输出: name=Joseph&id=123
我们可以查看键form来获取POST请求的负载数据。


data_post = r_post.json()
print(data_post['form']) # 输出: {'name': 'Joseph', 'id': '123'}


总结


本节课中,我们一起学习了如何使用Python的Requests库进行HTTP通信。我们介绍了如何发送GET请求和POST请求,如何检查响应状态码、头部信息和内容,以及如何通过查询字符串(GET)或请求体(POST)向服务器发送数据。理解这些基本操作是进行Web API交互和数据工程任务的重要基础。
006:Python样式指南与编码实践


在本节课中,我们将学习如何编写清晰、一致且易于维护的Python代码。我们将重点介绍PEP 8样式指南的核心原则、关键的编码惯例,并了解如何使用静态代码分析工具来确保代码质量。


🎯 编写可读代码的重要性

当你编写代码时,需要确保团队成员能够轻松阅读和理解它。这项任务需要遵循一定的编码标准和惯例。

Python官方发布了一份名为 Python增强提案第8号(PEP 8) 的文档,它提供了使Python代码可读且格式一致的惯例和指南。


✨ 提升代码可读性的关键指南


上一节我们介绍了PEP 8的重要性,本节中我们来看看提升代码可读性的具体指南。
缩进:使用空格而非制表符

PEP 8建议使用空格而非制表符进行缩进。


不同的文本编辑器和集成开发环境(IDE)对制表符所代表空格数的解释可能不同。例如,一个编辑器可能将制表符解释为三个空格,而另一个可能解释为四个。
使用制表符缩进可能导致代码格式不统一,从而引发格式错误。为了避免此类错误,你应该在缩进代码时使用一致数量的空格。
为了统一性,指南建议在代码的每个缩进层级使用四个空格。四个空格足以保证良好的可读性。
# 正确示例:使用四个空格缩进
if condition:
statement1
statement2

请注意,示例中的四个点是为了描绘四个空格而添加的。

使用空行分隔代码块

PEP 8还建议使用空行来分隔代码中的函数和类。
空行有助于界定代码不同部分的开始和结束。

# 不遵循PEP 8的示例:函数和类之间没有空行
def function1():
pass
class UserClass:
pass

# 遵循PEP 8的示例:函数和类之间有空行
def function1():
pass
class UserClass:
pass

在运算符和逗号周围使用空格

为了提高代码可读性,应在运算符周围和逗号后使用空格。使用空格会使命令看起来更宽松、更清晰,从而提升命令的可读性。
以下是具体示例:


- 当你写
A=B+C而没有任何空格时,可能会令人困惑。 - 然而,当你添加空格后,例如
A = B + C,可读性就提高了。
🔧 保持代码一致性与可管理性的编码惯例
上一节我们学习了提升可读性的格式指南,本节中我们来看看一些保持代码一致性和可管理性的编码惯例。


将大块代码封装在函数中


一个关键的编码惯例是为包含较大代码块的功能创建独立的函数,然后从主程序中调用这些函数。
例如,在以下代码中,if-else 语法没有封装成函数,每次需要该功能时都必须重写。然而,如果你将功能写成函数 function_1,它就可以被轻松调用。


# 未使用函数,代码重复
if a > b:
c = a
else:
c = b

# 使用函数,提高复用性
def get_max_value(x, y):
if x > y:
return x
else:
return y

c = get_max_value(a, b) # 调用函数

这种方式提高了代码的执行速度,并以更方便的方式支持代码块的重用。

函数和文件的命名:小写字母加下划线
另一个编码惯例是使用小写字母和下划线来命名函数和文件。
Python本身使用这种命名约定,并且许多内置库和预定义函数都遵循这一通用命名惯例。因此,使用小写函数名(最好带下划线)是明智的,这能使函数名更具独特性。
例如:
- 不要写成:
CompSurfaceRadiation() - 应该写成:
comp_surface_radiation()



此规则的一个例外是Python包的命名,通常不鼓励使用下划线。例如,应写为 mypackage 而不是 my_package。


类的命名:使用驼峰命名法

使用驼峰命名法命名类也是一个编码惯例。

驼峰命名法(或大驼峰命名法)是编码社区广泛接受的类命名约定。它也有助于在代码中区分类和函数。

例如:
- 不要写成:
class la_sirrel_c - 最佳实践是:
class LaSirrelC(L、S和C大写)

常量的命名:全大写字母加下划线

使用全大写字母并用下划线分隔单词的命名惯例,以保持一致性。

名称通常表明常量的用途,例如:MAX_FILE_UPLOAD_SIZE。


🔍 静态代码分析

我们讨论了编码惯例和指南,软件开发人员通常使用静态代码分析来管理对这些样式指南的遵从性。

静态代码分析是一种在不执行代码的情况下,根据预定义的样式和标准来评估代码的方法。

静态分析有助于发现诸如编程错误、违反编码标准、未定义的值、语法违规和安全漏洞等问题。
你可以使用 Pylint 等库来检查你的Python代码是否符合PEP 8指南。

📝 总结

本节课中我们一起学习了编写一致代码的重要性,它有助于所有团队成员轻松阅读和理解代码。
PEP 8提升代码可读性的指南包括:
- 使用四个空格进行缩进。
- 使用空行分隔函数和类。
- 在运算符周围和逗号后使用空格。
保持代码一致性和可管理性的编码惯例包括:
- 将大块代码封装在函数内部。
- 使用小写字母加下划线命名函数和文件。
- 使用驼峰命名法命名类。
- 使用全大写字母加下划线命名常量。

最后,我们了解了可以使用静态代码分析方法,在不执行代码的情况下,根据预定义的样式和标准来评估你的代码。
007:《Python数据工程项目课程》- 单元测试 🧪

在本节课中,我们将学习单元测试。我们将定义单元测试,解释其流程,学习如何构建和执行单元测试,并查看测试的输出结果。



什么是单元测试? 🔍
单元测试是一种验证代码单元是否按设计运行的方法。一个“单元”是应用程序中一个较小的、可测试的部分。
以下是一个单元的例子,它包含两个函数:square 和 doubler,位于 my_module.py 文件中。

def square(number):
return number ** 2

def doubler(number):
return number * 2
单元测试流程概览 📊


为了开发单元测试,我们将使用 unittest 库。这是一个已安装的Python模块,提供了一个包含测试功能的框架。
让我们简要回顾一下从单元测试到发布到生产代码库的端到端测试流程。

在代码开发过程中,你需要测试每个单元。测试分两个阶段进行。

第一阶段:本地系统测试

在第一阶段,你将在本地系统上测试单元。如果测试失败,你需要确定失败原因并修复问题。然后,你将再次测试该单元。


第二阶段:服务器环境测试
在单元测试通过后,你需要在服务器环境中测试该单元,例如持续集成/持续交付(CI/CD)测试服务器。

如果单元在服务器测试中失败,你将收到失败详情。你需要确定并修复问题。
一旦单元通过服务器测试,该单元就会被集成到最终的代码库中。

如何构建单元测试 🛠️

在概述了单元测试流程之后,让我们回顾一些测试函数,以理解如何构建单元测试。

请注意单元代码和单元测试代码。单元文件名是 my_module.py。单元测试文件则在文件名前或后附加了“test”一词。这是一个良好的命名约定,有助于清晰地区分单元文件和单元测试文件。
以下是创建单元测试文件的步骤。


第一步:导入 unittest 库


首先,导入 unittest Python库。
import unittest

第二步:导入要测试的函数
接下来,导入要测试的函数。例如,要从 my_module 单元导入 square 和 doubler 函数进行测试,请键入:
from my_module import square, doubler


第三步:构建单元测试类
然后,构建单元测试类,以便从单个类对象调用单元测试。例如,要创建一个名为 TestMyModule 的类,请输入:

class TestMyModule(unittest.TestCase):

请注意,类名在单元名前加了“Test”前缀。在示例中,这是一个良好的命名约定,在类名前加上“test”前缀有助于区分单元类和单元测试类。


第四步:使类继承 unittest.TestCase

接下来,使该类继承 unittest 库的 TestCase 类。例如,TestCase 是 unittest 库的测试用例类。继承该类允许你利用 TestCase 类中的现有方法。
第五步:创建测试函数

然后,在单元测试类中创建与每个需要测试的函数相对应的函数。例如,在 TestMyModule 类中,两个函数 test_square 和 test_doubler 对应于 my_module 单元中的 square 和 doubler 函数。
请注意,确保在单元测试模块中,函数名以 test 开头,因为只有以 test 开头的函数才会运行。

第六步:创建测试用例


最后,你可以创建测试用例。在创建测试用例时,添加一个或多个断言方法,以确保满足单元测试条件。
一个常用的断言函数是 assertEqual。请注意,在代码中,该方法已添加到 TestCase 类中。


assertEqual 函数比较两个值或实体,并判断它们是否相等。该方法用于检查函数是否返回正确的值。

assertEqual 函数接收的参数之一是实际值。对于实际值,你将调用要测试的函数。第二个参数是期望值,你将在其中添加函数预期返回的值。

在示例中,第一个测试是针对 square 函数,使用数字 2。如果函数正确执行,它应该返回值 4。

作为测试的一部分,首先评估函数。然后比较两个值,看它们是否相等。根据比较的输出,测试通过或失败。
查看测试输出 📈
运行测试文件后,会生成一个输出。输出显示测试结果以及一些附加信息。例如,如果输出显示在 0 秒内运行了两个测试,并且显示一个点 .,则表示测试通过,两个函数都正确实现了。
但是,如果函数没有正确实现会发生什么?

考虑 square 函数,你编写的代码是计算一个数的立方而不是平方。函数会失败,并生成一个输出。

让我们回顾一下失败的单元测试的示例输出。输出清楚地显示单元测试失败。例如,输出显示 FAILED test_square (__main__.TestMyModule)。你还可以查看单元测试失败的函数。例如,test_square self.assertEqual(square(2), 4) 表示 square 函数失败。AssertionError: 8 != 4 表示值不匹配。详细的输出使你能在实际部署解决方案之前纠正错误。
总结 📝
本节课中,我们一起学习了以下内容:
- 单元测试是一种验证代码单元是否按设计运行的方法。
- 在代码开发过程中,每个单元都会被测试。单元测试分两个阶段进行。一旦单元通过服务器测试,它就会被合并到最终的代码库中。
- 确保测试文件在文件名前或后附加“test”一词,以清晰地区分它们与模块文件。
- 你可以使用不同的测试函数来构建单元测试。
assertEqual函数是一种常用的断言方法,用于比较两个值。- 你可以查看单元测试输出,并确定测试是通过还是失败。
008:Python打包教程


在本节课中,我们将学习Python中模块、包和库的核心概念,并掌握如何创建、验证和使用一个Python包。


🧩 Python模块、包与库


模块、包和库是Python中频繁使用的术语。上一节我们介绍了课程目标,本节中我们来看看这些术语的具体含义。

Python模块

一个Python模块是一个包含Python定义、语句、函数和类的 .py 文件。
你可以将模块导入到其他脚本或笔记本中使用。例如,考虑一个名为 module.py 的模块,它包含两个函数。
第一个函数是 square(number),它计算输入数字的平方并返回结果。其代码表示为:
def square(number):
return number ** 2
第二个函数是 double(number),它将输入数字加倍并返回结果。其代码表示为:
def double(number):
return number * 2
如果该模块文件位于同一目录下,你可以导入并使用其中的函数。
考虑使用 square 函数配合 print 命令:
print("4^2 =", square(4))
输出将显示为 4^2 = 16。
类似地,对于值为4的 double 函数:
print("2*4 =", double(4))
输出是 2*4 = 8。

Python包

一个包是将多个Python模块组织到一个目录中,并且该目录包含一个 __init__.py 文件,这将其与普通的脚本目录区分开来。


示例展示了在父目录下的 my_project 包,它包含两个模块:module1.py 和 module2.py。

它同时也包含 __init__.py 文件。

当你导入一个模块或包时,Python创建的对应对象类型始终是 module。

请注意,模块和包的区别仅在于文件系统层面。


Python库
一个库是包的集合,或者它本身可以是一个单独的包。


示例包括 numpy、pytorch 和 pandas。

需要注意的是,术语“包”和“库”经常互换使用。因此,numpy、pytorch 和 pandas 也常被称为包。
🛠️ 创建Python包的步骤


理解了核心概念后,本节中我们来看看如何一步步创建一个Python包。


考虑有两个模块。module1.py 包含 square 和 double 两个函数。module2.py 包含一个 mean 函数。为了使 my_project 文件夹成为一个包,你必须在 my_project 文件夹中有一个 __init__.py 文件。
__init__.py 文件的内容必须是:
from . import module1
from . import module2
以下是创建包的典型步骤:
首先,创建一个以包名命名的文件夹。
然后,创建一个空的 __init__.py 文件。
接着,创建所需的模块文件。
最后,在 __init__.py 文件中,添加引用包中所需模块的代码。




✅ 验证Python包
创建包之后,你需要验证它是否能正常工作。以下是验证包的步骤:


首先,打开一个bash终端。
确保当前目录与你的包所在的文件夹处于同一层级。
在shell中运行 python 命令以打开Python解释器。
在Python提示符下,键入 import 后跟项目名称,例如:
import my_project
如果该命令运行无误,则表明包已成功加载。



测试包功能的一般结构是:包名.模块名.函数名(参数)。

例如,使用 my_project.module1.square(2),该函数将返回值 4。
🚀 使用Python包
创建并验证包之后,你可以在其他脚本中使用它,前提是包文件夹位于同一目录下。
在这种情况下,你在父目录中有一个 test.py 文件。
你可以导入包中的函数,例如使用以下Python代码:
from my_project.module1 import square, double
from my_project.module2 import mean
print("4^2 =", square(4))
print("2*4 =", double(4))
print("(2+1+3)/3 =", mean([2, 1, 3]))
然后运行这些函数并检查是否得到正确的结果。


📝 课程总结
本节课中我们一起学习了Python打包的核心知识。
我们了解到:
- Python模块 是一个包含Python定义、语句、函数和类的
.py文件。 - Python包 是将多个Python模块组织到一个包含
__init__.py文件的目录中。 - Python库 是包的集合,或者本身可以是一个单独的包。
要创建一个包,你需要:
- 创建一个以包名命名的文件夹。
- 创建一个空的
__init__.py文件。 - 创建所需的模块文件。
- 在
__init__.py文件中添加引用所需模块的代码。

你可以通过bash终端验证包。创建包后,如果包文件夹位于同一目录下,你可以在其他脚本中使用它。

浙公网安备 33010602011771号