今天,我们将看看如何在对 Python 有基本了解的情况下开始你的第一个数据工程项目。
如果您对 Python 有一定的了解并且刚刚开始使用 Dagster,本指南最有用。如果你是数据工程的新手,并且想从某个地方开始了解它在 Python 中的工作方式,这也很有帮助。
在本分步指南中,我们将放大 Dagster 中的资产,以帮助你了解如何创建成功的数据工程管道。在此过程中,我们将分享一些更有用的提示和技巧,以编写遵循最佳实践的干净、可维护的 Python 代码。
让我们开始吧!
数据工程涉及构建可以大规模存储、处理和分析数据的系统。
例如,数据工程师可能会创建一个管道,该管道按固定计划从不同源提取数据,将其转换为有用的格式,然后将其加载到数据库中以供进一步分析。这是一项传统的 ETL 任务,但他们也可以构建可以自动集成、清理、验证和对数据执行复杂计算的系统。
这些工具非常有用,因为它们可以帮助组织以快速、可靠和可扩展的方式处理大型复杂数据集。
Python 是一种流行的数据工程语言,因为它具有强大的数据操作库,如 pandas 和 NumPy,它也是一种通用语言,可用于广泛的任务。
Dagster 是用于数据编排的开源解决方案,数据编排是自动化数据管道的过程,用于聚合、处理和存储支持应用程序和业务流程的信息。数据编排支持一系列应用程序,从内部商业智能到面向客户的关键服务。现代数据编排过程可能包括机器学习、数据科学和分析用例,范围从在几分钟内运行的简单线性数据流程到需要数天才能执行的大规模复杂数据处理任务,工作分布在数十台甚至数百台单独的计算机上。
Dagster 提供了几个关键组件来帮助用户构建和运行其数据管道,包括资产、运营和作业。
如果您想更详细地探索资产、运营和作业,请参阅 Dagster 文档。
启动新的 Dagster 项目后,将所有项目文件夹和文件保存在根目录中非常重要。根目录是我们项目文件系统中包含所有其他文件夹的第一个或最顶层目录。我们将在这里编写 Dagster 项目代码,保持这种方式组织起来很重要,原因有两个。
首先,根目录在使用相对路径时提供公共参考点。这有助于确保无论文件的位置如何,都可以一致地查找和引用文件。
其次,在部署项目时,根目录通常用作打包和部署过程的起点。这可确保包含所有必需的文件,并以正确的结构部署项目。
考虑到这一点,让我们为您的项目创建一个新目录:
mkdir my_dagster_project
然后,我们可以使用以下命令将工作目录更改为项目的根目录:cd
cd my_dagster_project
接下来,我们将在根目录中设置一个虚拟环境,它允许在单独的项目中使用不同版本的 Python 和库,而不会相互干扰。
我们可以将虚拟环境命名为您想要的任何名称。在此示例中,我们使用 ..dag-venv
在基于 Unix 的操作系统(如 Linux 和 macOS)中,文件名前的点 (.) 表示应隐藏该文件。这些通常是通常不打算由用户直接访问或修改的系统文件。
点是操作系统用来将此类文件标识为隐藏的约定。默认情况下,当您使用类似 的命令列出目录的内容时,不会显示这些文件。但是,您仍可以通过显式指定这些文件的名称或使用显示隐藏文件(如 )的命令来访问这些文件。ls
ls -la
python3 -m venv .dag-venv
然后,激活虚拟环境:
source ./.dag-venv/bin/activate
您可以使用此可选命令来确认您所在的 Python 版本:
$(dag-venv) python3 --version
作为参考,在撰写此博文时,我使用的是 3.10.9 版
让我们首先通过在终端中运行以下命令来安装 Dagster 和其他您需要的 Python 包:
# run in a terminal in your favorite python environment
pip install dagster dagit pandas
最好验证已安装的 Dagster 版本:
dagster --version
作为参考,在写这篇博文时,我使用的是 Dagster 的 1.2.6 版。
Dagster 通过以下命令提供了一个有用的“基架”项目:
dagster project scaffold --name dagster-tutorial
我们将我们的项目命名为“dagster-tutorial”,但您可以将其替换为您喜欢的任何名称。
此时,您应该会看到一条消息,表明您走在正确的轨道上:
Success! Created dagster-tutorial at /Users//my_dagster_project/dagster-tutorial
在我们继续之前,了解运行时会发生什么会很有帮助。您会注意到这会在根目录中创建一堆文件:dagster project scaffold --name dagster-tutorial
这是一个标准的Dagster模板,可以轻松入门,而无需从头开始创建所有必要的文件。我们称之为代码脚手架:自动生成软件应用程序的基本结构或代码框架。它通过提供构建应用程序的起点来节省开发人员的时间。它还可以帮助确保代码的一致性和结构,使开发人员随着时间的推移更容易理解和维护应用程序。
在上一篇文章中,我们更详细地介绍了如何使用不同的工具管理依赖项。该文件允许我们指定我们需要的任何 Python 包。dagster-tutorial/setup.py
在 setup.py 文件中,你将找到以下代码:
from setuptools import find_packages, setup
setup(
name="dagster_tutorial",
packages=find_packages(exclude=["dagster_tutorial_tests"]),
install_requires=[
"dagster",
"dagster-cloud"
],
extras_require={"dev": ["dagit", "pytest"]},
)
一旦我们定义了我们的依赖项和库,Dagster 将自动管理它们的安装和执行。
其中一些文件对于运行 Dagster 至关重要。例如,当您查看文件夹下方时,您会发现一个包含以下代码的文件:dagster_tutorial
__init__.py
from dagster import Definitions, load_assets_from_modules
from . import assets
all_assets = load_assets_from_modules([assets])
defs = Definitions(
assets=all_assets,
)
稍后我们将详细解释什么是资产,但就目前而言,此文件加载我们将很快创建供应用程序访问的资产。资产本身在同一文件夹中的 assetys.py 文件中的代码中定义,并使用命令 .__init__.pyfrom 导入。进口资产
在文件中,您会注意到以下代码行:__init__.py
defs = Definitions(
assets=load_assets_from_modules([assets])
)
名为 的对象收集要在 Dagster 项目中用于代码位置的所有函数和管道。其中包括资产、计划、传感器、作业、资源、执行程序和记录器。将所有这些对象放入有助于更轻松地管理和组织代码。Definitions
defs
Definitions
注意:是 Dagster 从 1.2 版开始的最新增强功能,如果您参考较旧的教程,您可能会看到一个名为 的类似概念。 是一个更加简化的 API,它在减少样板文件的同时提供更多功能。Definitions
repositories
Definitions
Dagster 将用户定义的代码与 Web 服务器和守护程序等系统工具分开。Dagster 不是将代码直接加载到这些工具中,而是使用称为序列化的过程来允许工具与代码交互。这种分离有助于保持系统井井有条,并防止系统的不同部分直接交互可能引起的问题。
最重要的是,这意味着:
序列化是将复杂的数据结构(如对象、列表和字典)转换为易于存储、传输或共享的格式的过程。
这在数据工程工具中尤其重要,因为需要跨不同的应用程序保存、传输或使用大量数据。
这在达格斯特中是如何工作的?当Dagster使用“序列化边界”时,这意味着在用户定义的代码(例如对象)和系统工具之间传递的任何数据首先被序列化为可以在不同系统之间轻松传输的通用格式。Definitions
asset是 Dagster 中的关键组件。如前所述,asset是持久存储中的对象,例如表、文件或持久化机器学习模型。软件定义的asset是一个 Dagster 对象,它将asset耦合到用于生成其内容的函数和上游asset。软件定义的asset支持一种声明性的数据管理方法,其中代码是关于哪些数据asset应该存在以及如何计算这些asset的事实来源。
简单来说,软件定义的asset是 Dagster 中的一个对象,用于定义数据的存储和计算方式。它将数据(asset)连接到生成它的函数以及用于创建它的其他数据(上游asset)。asset是可重用且经过版本控制的数据或代码片段,可用作 Dagster 管道中的输入和输出。其中包括 SQL 脚本、数据文件或机器学习模型。
借助软件定义的asset,您可以使用声明性方法管理数据,这意味着您可以定义应存在哪些数据以及如何通过代码计算数据。此方法有助于保持数据管理的井井有条且一致,并确保代码是数据处理方式的真实来源。
当创建或刷新asset时,我们说它是“具体化的”——这意味着已经创建了资产的新实例并提交到存储中。
让我们创建两个资产来下载前 10 个 HackerNews 故事。
在我们的 Dagster 项目中,让我们将以下代码添加到文件中:dagster-tutorial/dagster_tutorial/assets.py
import pandas as pd
import requests
from dagster import Output, asset
@asset
def hackernews_top_story_ids():
"""
Get top stories from the HackerNews top stories endpoint.
API Docs: https://github.com/HackerNews/API#new-top-and-best-stories
"""
top_story_ids = requests.get(
"https://hacker-news.firebaseio.com/v0/topstories.json"
).json()
return top_story_ids[:10]
# asset dependencies can be inferred from parameter names
@asset
def hackernews_top_stories(context, hackernews_top_story_ids):
"""Get items based on story ids from the HackerNews items endpoint"""
results = []
for item_id in hackernews_top_story_ids:
item = requests.get(f"https://hacker-news.firebaseio.com/v0/item/{item_id}.json").json()
results.append({item['title'],item['by'],item['url']})
df = pd.DataFrame(results)
context.log.info(df)
return Output(value=df)
现在,在终端中运行该命令。这将启动 Dagster 的用户界面:dagster dev
$ dagster dev
在浏览器中,导航到 http://localhost:3000/。这是您可以在浏览器上“找到”正在运行的Dagster应用程序的本地地址。
在“部署”选项卡下,单击“全部具体化”以运行管道并创建资产。我们使用术语“物化”来描述创建或刷新资产的过程,这意味着已创建并保存了资产的新版本。此管道使用 Dagster 默认值将结果保存到磁盘上的 pickle 文件中。
出于本教程的目的,我们还将使用命令将 Pandas 数据帧的内容输出到 Dagster 的日志记录系统。如果单击顶部菜单中的“运行”选项卡,您将看到运行的详细信息以及生成的数据:context.log.info(df)