【Python程序设计】 工厂模式【07/8】

一、说明

        我们探索数据工程中使用的设计模式 - 软件设计中常见问题的可重用解决方案。 以下文章是有关 Python 数据工程系列文章的一部分,旨在帮助数据工程师、数据科学家、数据分析师、机器学习工程师或其他刚接触 Python 的人掌握基础知识。
        迄今为止,本初学者指南包括:

  • 第 1 部分:Python 包探讨了 Python 模块、Python 包的基础知识以及如何将模块导入您自己的项目。【Python 程序设计】包和数据人员入门【01/8】 
  • 第 2 部分:介绍了依赖项管理和虚拟环境。【Python 程序设计】数据人员入门【02/8】
  • 第 3 部分: 项目的最佳实践,涵盖了构建项目的 9 个最佳实践和示例。【Python程序设计】 项目的最佳实践【03/8】
  • 第 4 部分: Dagster 管道,我们探讨了设置 Dagster 项目以及数据资产的关键概念。【Python程序设计】 从 Python 项目到 Dagster Pipelines【04/8】
  • 第 5 部分:我们将介绍环境变量的重要性以及如何使用它们。【Python程序设计】Python 中的环境变量【05/8】
  • 第 6 部分:类型提示,或类型提示如何减少错误。
  • 第7 部分:模式,或学习设计模式,它们是软件设计中常见问题的可重用解决方案。【Python程序设计】 工厂模式【07/8】


二、Python 编程中的工厂模式

        在本系列中,你了解了数据工程中的 Python 最佳实践,以及如何构建更健壮和可扩展的软件。今天,我们将采用一种称为设计模式的更高级编程概念,它是软件设计中常见问题的可重用解决方案。您可能会在数据工程项目中遇到这些问题。

        我们将看看什么是设计模式,为什么要使用它们,并特别深入探讨一种模式:工厂模式。我们还将讨论为什么数据工程师会从使用工厂模式中受益。

        工厂模式优雅地简化了数据连接器的创建,并使现有数据基础结构更具可扩展性。这对于处理具有不同处理需求的各种数据源的数据工程师特别有用。

        工厂模式定义:在软件设计中,“工厂模式”允许您创建一个类,其子类决定要实例化哪个类。工厂模式允许在不指定将要创建的确切对象类的情况下创建对象,从而促进代码中的松散耦合和可伸缩性。此模式通常使用工厂方法或工厂类来实现,以基于输入条件或条件生成对象的实例。

        工厂模式称为“创建设计模式”(本文稍后将对此进行说明)。

        在本课程的这一部分中,我们将了解工厂模式如何在数据工程中实现可重用性、可伸缩性和可维护性。

三、 设计模式 101

Python 中的设计模式作为模板工作,可以应用于重复性任务或问题,因此在数据工程中非常有用。对于 Python 数据工程师来说,设计模式为数据处理和集成任务中反复出现的挑战提供了结构化且高效的解决方案。它们还提供共享词汇表,促进团队成员之间更清晰的沟通,从而实现更一致和协作的软件设计。

3.1 设计模式的类型

Python 中的设计模式以及一般编程中的设计模式通常被认为是中级到高级概念,因为它们通常需要了解编程原理、面向对象设计以及识别和抽象更大、更复杂的系统(即代码架构)中反复出现的问题的能力。Python的设计模式通常分为三种类型:

  1. 创建模式:这些模式包括工厂模式,可用于实例化和管理数据库连接,确保无论是连接到 SQL 数据库还是 NoSQL 存储,该过程都得到简化且一致
  2. 结构模式:提供有关组织和链接不同组件的指导,在集成不同的数据源时可能非常宝贵。例如,您可以使用适配器模式将来自旧系统的数据与现代分析平台协调,从而确保无缝数据流
  3. 行为模式:提供对象之间有效沟通和交互的策略。例如,可以使用观察者模式来监视数据集中的更改:想象一下,每当新数据到达时,数据引入过程都会通知多个下游处理任务。

3.2 为什么要在数据工程中使用设计模式?

        设计模式为数据工程任务提供了明显的优势,这些任务与软件设计的核心原则相呼应:

  1. 声明:通过设计模式,数据工程师可以定义最终目标或他们想要实现的目标,而不会陷入程序应该如何执行的细节中。通过定义你想要什么,底层逻辑会处理“如何”。这种抽象简化了过程。
  2. 可 重用: 将设计模式视为蓝图。正如建筑计划可用于建造各种建筑物一样,这些模式可以应用于不同的管道或项目,确保您的工作不仅限于一个解决方案,而是可以多次利用。
  3. 一致: 数据世界是广阔而多样的。通过采用设计模式,数据工程师可确保数据资产(无论其来源或应用程序如何)都遵循一致的结构和行为。这使得数据操作可预测并减少异常,从而产生更强大的数据系统。

        通过将资产工厂等设计模式集成到数据工程工作流(从数据提取、分析数据、数据转换等)中,我们为更顺畅的操作、更少的错误和更高效的系统铺平了道路,确保管理和优化数据以获得最佳结果。

每个设计模式都用于防止在项目缩放时出现特定问题。今天,我们将重点介绍工厂模式,该模式用于构建多个类似的东西,以促进集中配置、标准化测试,并在遵守一致性的同时允许灵活性。

四、工厂模式如何工作?

工厂模式被归类为创建模式,因为它们在 Python 编程中创建对象。它们根据某些条件语句或参数返回不同的对象。

4.1 将对象创建与主应用程序分离

        将工厂模式视为公司中的一个专业部门,只专注于生产某些产品。该部门负责制造的所有细节,公司的其他部门只需在需要时要求产品,而不必担心其制造方式。

        同样,工厂模式负责创建特定对象的所有细节。应用程序的其余部分不需要知道这些对象的创建方式或它们需要哪些参数。它只是要求“工厂”生产对象,并信任它来处理其余的。这种分离使代码更清晰、更易于理解。

4.2 Python 中的工厂模式

        在 Python 中,实现工厂模式特别精简,这要归功于它的动态类型和一流的函数。您可以从工厂函数返回不同的类甚至函数,而无需太多样板。

        此外,许多 Python 库和框架利用工厂模式或类似工厂的模式,即使它不是显式的或完全相同的。例如,像SQLAlchemy这样的ORM(对象关系映射库)使用工厂来创建数据库会话对象。SQLAlchemy 可以比作工厂模式,因为它生成新的会话实例,充当数据库通信的主要接口。sessionmaker()

4.3 使用 Python 在数据工程中使用工厂模式:示例

        Python 的内置功能(如装饰器)可用于增强工厂模式。例如,装饰器可用于向工厂注册类,从而扩展工厂的功能,而无需显式修改它。

        想象一下数据工程中的一个常见场景:用于操作来自不同文件格式的数据的数据管道:CSV、JSON 和 XML 文件。根据文件类型,应应用不同的分析步骤。

        我们将使用一个简单的字典作为这些文件解析器的“注册表”,并将函数作为我们的工厂。

        首先,我们将定义解析函数:

import csv
import json
import xml.etree.ElementTree as ETdef parse_csv(file_path):with open(file_path, mode='r') as file:reader = csv.reader(file)return list(reader)def parse_json(file_path):with open(file_path, mode='r') as file:return json.load(file)def parse_xml(file_path):tree = ET.parse(file_path)root = tree.getroot()return root  # you'd typically add more logic to process the XML tree

        然后,我们将定义一个装饰器来注册这些解析器:

PARSERS = {}def register_parser(file_type):def decorator(fn):PARSERS[file_type] = fnreturn fnreturn decorator

        我们将注册我们的解析器:

@register_parser('csv')
def csv_parser(file_path):return parse_csv(file_path)@register_parser('json')
def json_parser(file_path):return parse_json(file_path)@register_parser('xml')
def xml_parser(file_path):return parse_xml(file_path)

        最后,我们将编写一个函数来获取正确的解析器,并使用工厂来解析文件:

def get_parser(file_type):return PARSERS.get(file_type)data_csv = get_parser('csv')('data.csv')
data_json = get_parser('json')('data.json')
data_xml = get_parser('xml')('data.xml')

        对于数据工程师来说,处理多种文件格式是很常见的,并且能够使用新的解析器(如XML,Parquet等)轻松扩展系统至关重要。通过此设置,数据工程师只需定义一个新的解析函数并将其注册到装饰器,即可轻松扩展系统以支持新的文件类型。

        无需接触现有的工厂逻辑,使其易于维护和扩展。通过将工厂模式与装饰器一起使用,我们可以简化此过程并维护更干净、更模块化的代码。

五、使用工厂模式进行数据工程

        数据工程师或数据科学家经常将工厂模式用于日常任务,例如批处理、构建实时数据流和 ETL 管道。

        例如,假设工作流中有各种类型的数据连接,例如数据库、文件或 API。您可以使用工厂模式根据当时的需求为您创建正确的连接,而不是手动创建与每个连接的连接。可以把它想象成一条装配线,在需要时准确地生产你需要的东西,而不会用不必要的细节弄乱其余的代码。

5.1 在数据管道中

        让我们考虑一个需要连接到不同类型的数据库的场景,如MySQL和PostgreSQL。工厂模式可用于根据给定输入创建适当的数据库连接。下面是一个说明此模式的简单示例:

        让我们首先定义每个数据库的连接:

import mysql.connector
import psycopg2def connect_mysql(host, user, password, database):connection = mysql.connector.connect(host=host,user=user,password=password,database=database)return connectiondef connect_postgresql(host, user, password, database):connection = psycopg2.connect(host=host,user=user,password=password,dbname=database)return connection

        接下来,我们将定义一个装饰器来注册数据库连接:

DB_CONNECTIONS = {}def register_db_connector(db_type):def decorator(fn):DB_CONNECTIONS[db_type] = fnreturn fnreturn decorator

        然后,我们将注册连接:

@register_db_connector('mysql')
def mysql_connector(host, user, password, database):return connect_mysql(host, user, password, database)@register_db_connector('postgresql')
def postgresql_connector(host, user, password, database):return connect_postgresql(host, user, password, database)

        最后,我们将编写一个函数来获取正确的连接器,并使用工厂来获取适当的数据库连接:

def get_db_connector(db_type):if db_type not in DB_CONNECTIONS:raise ValueError(f"Unsupported database type: {db_type}")return DB_CONNECTIONS[db_type]# Example usage:
mysql_conn = get_db_connector('mysql')('localhost', 'user', 'password', 'mydb')
postgres_conn = get_db_connector('postgresql')('localhost', 'user', 'password', 'mydb')

        通过此设置,将来添加对新型数据库连接的支持非常简单。我们首先定义连接函数,然后使用装饰器注册它。无需更改其他部件,展示了工厂模式的可维护性和可扩展性优势。

六、实际方案中的工厂模式

工厂在以下情况下特别有用:

  1. 处理可能随时间变化的外部库或系统,让您隔离这些更改
  2. 实现系统的插件或扩展
  3. 需要出于对象池、延迟初始化或日志记录等目的控制对象实例化

我们将看两个示例,说明工厂资产在现实世界中的工作方式。

6.1 示例 1:抓取维基百科

        当您需要抓取不同类型的页面但希望为所有页面保持一致的界面时,工厂模式在网页抓取中特别有用。让我们看看工厂模式如何用于按人口抓取维基百科的国家和依赖关系表:

        首先,请确保安装以下内容:

pip install requests
pip install beautifulsoup4

        然后,定义函数以从维基百科中抓取不同的表。假设维基百科可能有多个表以不同的格式表示这些数据。一个表可能是标准表,而另一个表可能是针对移动设备优化的。

from bs4 import BeautifulSoup
import requestsdef scrape_standard_table(url):page = requests.get(url)soup = BeautifulSoup(page.content, 'html.parser')# Assuming the first table on the page is the one of interesttable = soup.find_all("table")[0]rows = table.find_all("tr")data = []for row in rows[1:]:  # skipping the header rowcolumns = row.find_all("td")country = columns[0].get_text(strip=True)population = columns[1].get_text(strip=True)data.append((country, population))return datadef scrape_mobile_table(url):page = requests.get(url)soup = BeautifulSoup(page.content, 'html.parser')# Mobile tables might be different, for the sake of example let's assume they're div-basedtable_div = soup.find("div", {"class": "mobile-table"})rows = table_div.find_all("div", {"class": "row"})data = []for row in rows:country = row.find("div", {"class": "country"}).get_text(strip=True)population = row.find("div", {"class": "population"}).get_text(strip=True)data.append((country, population))return data

        然后,我们将定义一个装饰器来注册抓取函数:

SCRAPERS = {}def register_scraper(scraper_type):def decorator(fn):SCRAPERS[scraper_type] = fnreturn fnreturn decorator

        现在我们将注册我们的抓取函数:

@register_scraper('standard')
def standard_scraper(url):return scrape_standard_table(url)@register_scraper('mobile')
def mobile_scraper(url):return scrape_mobile_table(url)

        最后,我们将编写我们的函数来获取正确的抓取工具,并使用工厂从维基百科获取数据:

def get_scraper(scraper_type):if scraper_type not in SCRAPERS:raise ValueError(f"Unsupported scraper type: {scraper_type}")return SCRAPERS[scraper_type]# Example usage:
url = "https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population"
data_standard = get_scraper('standard')(url)
# data_mobile = get_scraper('mobile')(url)  # if you had a mobile URL

        在此示例中,添加对将来抓取不同格式的支持(如维基百科中的不同表结构)很简单:定义抓取函数,然后使用装饰器注册它。这可确保抓取代码保持模块化且易于扩展,而无需修改现有逻辑。

6.2 示例 2:数据编排

        Dagster 是一个数据编排器,可为数据处理的不同阶段(从引入到机器学习)提供单一管理平台。Dagster帮助安排和观察广泛的数据工程工具,Python作为其编程语言。它被数据工程师和数据科学家广泛用于数据科学、数据分析、大数据、机器学习等一系列应用。

        Dagster 的功能之一是能够管理资产,这些资产是数据计算的输出。资产表示一段数据或具有价值且值得跟踪的计算结果。这可以是数据库中的表、磁盘上的文件、模型工件等。资产通常是管道的输出。

        资源工厂是 Dagster 中的一项功能,允许用户以声明方式定义资产的生成方式。它们可以被视为通过定义生成资产所需的输入、输出和计算来创建资产的模板。

        让我们演练一个简单的示例,在该示例中,我们将通过在 Dagster 中应用 Factory 模式来重构现有代码块以生成一组资产。

        在开始之前,请确保安装Dagster:

pip install dagster dagster-webserver

        假设我们是非营利组织数据工程团队的一员。我们有一些现有的代码来查询捐赠者平台的 API 并将结果写入文件(CSV 或 JSON)。它目前看起来像这样:

from dagster import asset
import requests
import csv@asset
def volunteers():result = requests.get('www.donorplatform.org/api/v1/volunteers')with open('volunteers.csv', 'w') as f:writer = csv.writer(f)writer.writerows(result)@asset
def donations():result = requests.get('www.donorplatform.org/api/v2/donations')with open('donations.csv', 'w') as f:writer = csv.writer(f)writer.writerows(result)@asset
def donors():result = requests.get('www.donorplatform.org/api/v1/donors')with open('donors.json', 'w') as f:f.write(result)

        我们的运营团队最近扩大了对捐赠者平台的使用,并要求我们从 50 个新的 API 端点运行数据提取。这变得不守规矩且难以管理,因为您知道这将需要很长时间,数据工程师将偏离他们检索数据的方式,并且很难测试。

        使用我们新的 python 技能,让我们为此应用工厂模式来解决这些问题。

        首先,让我们定义可以配置的内容。需要为每个资产自定义三个部分:

  1. 资产的名称
  2. 它查询的终结点
  3. 结果保存为的文件类型

因此,我们将定义一个 JSON 对象来集中资产的可能配置。

specs = [{'name': 'volunteers','endpoint': 'v1/volunteers','file_type': 'csv'},{'name': 'donations','endpoint': 'v2/donations','file_type': 'csv'},{'name': 'donors','endpoint': 'v1/donors','file_type': 'json'}
]

        然后,我们将定义和泛化我们的资产函数,以采用规范并生成资产

spec = specs[0] # take a single spec as reference while building@asset(name=spec['name'])
def generic_asset():result = requests.get(f'www.donorplatform.org/api/{spec["endpoint"]}')with open(f'{spec["name"]}.f{spec["file_type"]}', 'w') as f:if spec["file_type"] == 'csv':writer = csv.writer(f)writer.writerows(result)elif spec["file_type"] == 'json':f.write(result)

        最后,让我们将通用资产包装在一个函数中,该函数将用作生成所有资产的工厂。该函数将采用规范并将其应用于我们的资产。

def generate_donor_platform_asset(spec):@asset(name=spec['name'])def _asset():result = requests.get(f'www.donorplatform.org/api/{spec["endpoint"]}')with open(f'{spec["name"]}.f{spec["file_type"]}', 'w') as f:if spec["file_type"] == 'csv':writer = csv.writer(f)writer.writerows(result)elif spec["file_type"] == 'json':f.write(result)return _asset

        在您的工厂中,您只需定义其他规格即可生产更多资产。以下是它在生产中的使用方式:

from dagster import Definitions, asset
import requests
import csvspecs = [{'name': 'volunteers', 'endpoint': 'v1/volunteers', 'file_type': 'csv'},{'name': 'donations', 'endpoint': 'v2/donations', 'file_type': 'csv'},{'name': 'donors', 'endpoint': 'v1/donors', 'file_type': 'json'},{'name': 'projects', 'endpoint': 'v1/projects', 'file_type': 'json'},{'name': 'fundraisers', 'endpoint': 'v1/fundraisers', 'file_type': 'csv'},
]def generate_donor_platform_asset(spec):@asset(name=spec['name'])def _asset():result = requests.get(f'www.donorplatform.org/api/{spec["endpoint"]}')with open(f'{spec["name"]}.f{spec["file_type"]}', 'w') as f:if spec["file_type"] == 'csv':writer = csv.writer(f)writer.writerows(result)elif spec["file_type"] == 'json':f.write(result)return _assetdefs = Definitions(assets=[generate_donor_platform_asset(spec) for spec in specs])

        如果您运行 ,您将可以访问 dagster 的 UI 和 localhost:3000 上的资产图。当您向列表中添加更多规范并重新加载定义时,您将看到生成的更多资产。dagster dev

        这是 Dagster 中资产工厂入门的基本数据工程示例。随着您深入研究 Dagster,您可以探索更高级的功能。Dagster还提供与许多数据库和数据系统的集成。这使得使用资源工厂以各种格式和位置生成资产变得容易。可以使用资产工厂在云存储系统上生成文件、执行 SQL 或训练机器学习模型。

        因此,python项目中的资产工厂提供了相同的三个好处:

  1. 声明:资源工厂允许您指定要生产的内容,而无需编写如何生成它的详细逻辑
  2. 可 重用:由于资源工厂是模板,因此可以在不同的管道或项目中重复使用它们
  3. 一致:使用资源工厂可确保以一致的方式生成资产,无论它们在何处或如何使用

七、结论

        工厂模式是数据工程师的宝贵工具,尤其是在处理不同类型的数据源或复杂对象创建时。它简化了您的代码,使其更具可重用性、可扩展性和可维护性。

        作为最流行的编程语言之一,在使用 Python 进行数据工程时,工厂模式非常有用。虽然这些也适用于其他语言,但您最有可能遇到 Python 作为通用编程语言,落后于大多数流行的数据工程任务工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/75436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman接口测试流程

一、工具安装 ● 安装Postman有中文版和英文版,可以选择自己喜欢的版本即可。安装时重新选择一下安装路径(也可以默认路径),一直下一步安装完成即可。(本文档采用英文版本)安装文件网盘路径链接&#xff1…

【分享】golang windows 运行报错 undefined: syscall.SIGUSR1

在跟着煎鱼大佬学习 Golang-gin的时候,"在优雅的重启服务篇" ,为了gin服务的热更新,采用了 endlessfresh的方案,安装endless后无法在windows本地调试,然后报错。 (优雅的重启服务-地鼠文档优雅的重启服务-我不怎么喜欢左写写&#…

蓝桥杯官网练习题(旋转)

题目描述 图片旋转是对图片最简单的处理方式之一,在本题中,你需要对图片顺时针旋转 90 度。 我们用一个 nm 的二维数组来表示一个图片,例如下面给出一个 34 的 图片的例子: 1 3 5 7 9 8 7 6 3 5 9 7 这个图片顺时针旋转 90 …

蓝桥杯官网填空题(振兴中华)

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 小明参加了学校的趣味运动会,其中的一个项目是:跳格子。 地上画着一些格子,每个格子里写一个字,如下所示&#xff1…

dnmp运行时404报错

dnmp运行时404报错 问题截图: dnmp简介 M1芯片(Arm CPU) 环境中搭建PHPNGINXMYSQL的利器,docker容器管理当前使用的软件,可以简单安装软件和扩展。 localhost.conf 原始文件如下: server {listen 8…

springmvc 获取项目中的所有请求路径

springboot/springmvc 获取项目中的所有请求路径 1. 编写业务代码 Autowiredprivate WebApplicationContext applicationContext;GetMapping("/getAllURL")public RestfulResult getAllURL() {// 获取springmvc处理器映射器组件对象 RequestMappingHandlerMapping无…

海康NVR(Network Video Recorder)启用SSH过程摸索

文章目录 海康NVR具备的特点启用SSH模式优劣比较启用SSH模式的优势启用SSH模式的坏处 Hik NVR启用SSH功能1,Web登录NVR2,SSH登录NVR SSH shell模式特点SSH shell模式指令作用1,简要帮助“help”可以列出常用的shell指令部分可用shell指令输出…

Android Handler 机制解析

1、前言 在 Android 开发中,Handler 的机制和运行原理这方面的知识可以说是每个人都需要熟悉的。这不仅是因为 Handler 是 Android 应用的基石之一,也因为 Handler 整体设计上也是十分优秀的。接下来我就梳理总结一下常见的 Handler 相关知识点。 2、基…

修复 ChatGPT 发生错误的问题

目录 ChatGPT 发生错误?请参阅如何修复连接错误! 修复 ChatGPT 发生错误的问题 基本故障排除技巧 检查 ChatGPT 的服务器状态 检查 API 限制 检查输入格式 清除浏览数据 香港DSE是什么? 台湾指考是什么? 王湘浩 生平 …

【漏洞复现】EnjoySCM存在文件上传漏洞

漏洞描述 EnjoySCM是一款适应于零售企业的供应链管理软件,主要为零售企业的供应商提供服务。EnjoySCM的目的是通过信息技术,实现供应商和零售企业的快速、高效、准确的信息沟通、管理信息交流。。 该系统存在任意文件上传漏洞,攻击者通过漏洞可以获取服务器的敏感信息。 …

【C#项目实战】控制台游戏勇士斗恶龙(1)——游戏初始设置以及开始界面

君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,最近开始正式的步入学习游戏开发的正轨,想要通过写博客的方式来分享自己学到的知识和经验,这就是开设本专栏的目的。希望…

植物大战僵尸各种僵尸攻略

前言 此文章为“植物大战僵尸”专栏中的009刊(2023年9月第八刊),欢迎订阅。版权所有。 注意: 1.本博客适用于pvz无名版; 2.pvz指植物大战僵尸(Plants VS Zonbies); 3.本文以耗费低做标准&am…

老太太阿姨收割机秀才被封

除了他自己和平台官方,恐怕没有人知道详细数字,不过坊间流传着一句话,叫“秀才和一笑倾城一场直播,就可以榨光一个省的老人低保 可见吸金是有多么恐怖 一笑倾城是秀才的“姊妹篇”,秀才专供老太太,一笑倾城…

uni-app:自带的消息提示被遮挡的解决办法(自定义消息提示框)

效果&#xff1a; 代码&#xff1a; 1、在最外层或者根组件的模板中添加一个容器元素&#xff0c;用于显示提示消息。例如&#xff1a; <div class"toast-container" v-if"toastMessage"><div class"toast-content">{{ toastMessa…

EMERSON A6500-CC 机架接口模块 AMS参数

EMERSON A6500-CC 机架接口模块 AMS参数 ModBus和机架接口模块设计用于工厂的高可靠性 最关键的旋转机械。它从所有AMS A6500 ATG模块读取参数 并通过ModBus TCP/IP和/或ModBus RTU&#xff08;串行&#xff09;输出这些参数。 此外&#xff0c;OPC UA可用于向第三方系统传输数…

华为Mate 60和iPhone 15选哪个?

最近也有很多朋友问我这个问题来着&#xff0c;首先两款手机定位都是高端机&#xff0c;性能和体验各有千秋&#xff0c;各自有自己的铁杆粉。 但是让人意想不到的是华为mate60近日在海外越来越受欢迎和追捧&#xff0c;甚至是引起了不少人的抢购&#xff0c;外观设计和…

最详细的CompletableFuture异步编程-进阶篇

1、异步任务的交互 异步任务交互指 将异步任务获取结果的速度相比较&#xff0c;按一定的规则( 先到先用 )进行下一步处理。 1.1 applyToEither applyToEither() 把两个异步任务做比较&#xff0c;异步任务先到结果的&#xff0c;就对先到的结果进行下一步的操作。 Complet…

C/C++操作加密与不加密的zip文件

为了后续的方便操作zip文件&#xff0c; 将所有的操作封装成了一个动态库了。 /*** \description 从压缩包文件中解压出指定的文件到指定的目录.* \author sunsz* \date 2023/09/09**/ LIBZIP_API int UnpackFile(const char* password, char zipfilename[], char filename_…

如何使用ArcGIS去除卫星影像上的云

虽然目前发布的地图都是对云量进行过筛选&#xff08;一般低于20%&#xff09;&#xff0c;但是还是有可能会遇到有云的情况&#xff08;特别是下载历史影像的时候&#xff09;&#xff0c;那么这些云应该怎么去除呢&#xff0c;我们可以尝试使用ArcGIS进行处理。 识别像素 将…

pb:垃圾收集函数

PB系统函数大全 - 垃圾收集函数 垃圾收集函数让应用程序能够控制何时开始收集系统产生的垃圾。 1、GarbageCollect() 功 能:强制系统立即开始收集垃圾。 语 法:GarbageCollect ( ) 返回值:无。 用 法:该函数强制系统立即开始收集垃圾。PowerBuilder将查找并标识未…