通过 Spark SQL 和 DataFrames 与外部数据源交互

文章目录

    • 前言
    • Spark SQL 与 Hive
      • UDF
    • 通过 Spark SQL Shell, Beeline 和 Tableau 查询
      • Spark SQL Shell
      • Beeline
      • Tableau
    • 外部数据源
      • 通过 JDBC 连接数据库
      • PostgreSQL
      • MySQL
    • 高阶函数
      • Explode 和 Collect
      • UDF
      • 内置函数
      • 高阶函数
    • 常用 DataFrames 和 Spark SQL 操作
    • 总结

前言

Spark 的数据源分为内部数据源和外部数据源,本文将讨论Spark SQL 与外部数据源之间的交互:

  • Spark 和 Hive 都会使用到的 UDF 函数
  • 通过 JDBC 连接各种外部数据源
  • 简单和复杂的数据类型和各种高阶运算符

还将了解使用Spark SQL查询Spark的一些不同工具,例如Spark SQL shell、Beeline和Tableau。

Spark SQL 与 Hive

Spark SQL 让 Spark 使用者编写的查询语句拥有更好的性能和更简单的写法(例如,声明式查询和优化过的存储),以及调用复杂的分析库(例如,机器学习)。并且,SparkSession提供了一个单一的统一入口点来操作Spark中的数据。

UDF

创建自己的PySpark或Scala UDF(user defined function)的好处是我们将能够在Spark SQL中使用它们, 而不需要关系该方法的内部实现。例如,数据科学家可以将ML模型包装在UDF中,以便数据分析师可以在Spark SQL中查询与分析,而不必了解模型的内部结构。
Spark SQL UDFs
创建

// In Scala
// Create cubed function
val cubed = (s: Long) => {s * s * s
}// Register UDF
spark.udf.register("cubed", cubed)// Create temporary view
spark.range(1, 9).createOrReplaceTempView("udf_test")
# In Python
from pyspark.sql.types import LongType# Create cubed function
def cubed(s):return s * s * s# Register UDF
spark.udf.register("cubed", cubed, LongType())# Generate temporary view
spark.range(1, 9).createOrReplaceTempView("udf_test")

创建完后使用:

// In Scala/Python
// Query the cubed UDF
spark.sql("SELECT id, cubed(id) AS id_cubed FROM udf_test").show()+---+--------+
| id|id_cubed|
+---+--------+
|  1|       1|
|  2|       8|
|  3|      27|
|  4|      64|
|  5|     125|
|  6|     216|
|  7|     343|
|  8|     512|
+---+--------+

PySpark 与 Pandas UDFs
在早期的时候通过 PySpark 使用 UDF 会使查询性能变慢,因为 python 的UDF 需要转化为 JVM 程序,为了解决这个问题,Spark 2.3 之后 Pandas UDF 被集成进了 Spark,只要数据是Apache Arrow格式,就不再需要序列化/反序列化数据。
Spark 3.0 之后,Pandas UDF 被拆分为Pandas UDFs 和 Pandas Function APIs.

  • Pandas UDFs

    在Apache Spark 3.0中,Pandas UDFs(用户定义函数)可以从Pandas UDFs中的Python类型提示中推断出Pandas UDF类型,例如pandas.Series、pandas.DataFrame、Tuple和Iterator。以前,需要手动定义和指定每个Pandas UDF类型。当前,Pandas UDFs中支持的Python类型提示的情况包括Series到Series、Series的Iterator到Series的Iterator、多个Series的Iterator到Series的Iterator,以及Series到Scalar(单个值)

  • Pandas Function APIs

    Pandas API允许直接将本地 Python 函数应用于 PySpark DataFrame,其中输入和输出都是Pandas实例。对于Spark 3.0,支持的Pandas函数API包括分组映射(grouped map)、映射(map)和联合分组映射(co-grouped map).

创建 UDF

# In Python
# Import pandas
import pandas as pd# Import various pyspark SQL functions including pandas_udf
from pyspark.sql.functions import col, pandas_udf
from pyspark.sql.types import LongType# Declare the cubed function 
def cubed(a: pd.Series) -> pd.Series:return a * a * a# Create the pandas UDF for the cubed function 
cubed_udf = pandas_udf(cubed, returnType=LongType())

通过 Pandas 使用该 UDF

# Create a Pandas Series
x = pd.Series([1, 2, 3])# The function for a pandas_udf executed with local Pandas data
print(cubed(x))# 输出
0     1
1     8
2    27
dtype: int64

作为 Spark UDF 使用

# Create a Spark DataFrame, 'spark' is an existing SparkSession
df = spark.range(1, 4)# Execute function as a Spark vectorized UDF
df.select("id", cubed_udf(col("id"))).show()# 输出
+---+---------+
| id|cubed(id)|
+---+---------+
|  1|        1|
|  2|        8|
|  3|       27|
+---+---------+

更多关于 Pandas UDF 的资料可以访问官方文档。

通过 Spark SQL Shell, Beeline 和 Tableau 查询

Spark SQL Shell

spark-sql CLI是执行Spark SQL查询的便捷工具。尽管该实用程序在本地模式下与Hive元数据存储服务通信,但它不会与Thrift JDBC/ODBC服务器(也称为Spark Thrift Server或STS)通信。STS允许JDBC/ODBC客户端通过JDBC和ODBC协议在Apache Spark上执行SQL查询。
$SPARK_HOME文件夹中执行以下命令启动 CLI:

./bin/spark-sql

创建表

spark-sql> CREATE TABLE people (name STRING, age int);

输出内容将包含表所在文件位置 /user/hive/warehouse/people

20/01/11 22:42:16 WARN HiveMetaStore: Location: file:/user/hive/warehouse/people
specified for non-external table:people
Time taken: 0.63 seconds

插入数据

spark-sql> INSERT INTO people VALUES ("Michael", NULL);
Time taken: 1.696 seconds
spark-sql> INSERT INTO people VALUES ("Andy", 30);
Time taken: 0.744 seconds
spark-sql> INSERT INTO people VALUES ("Samantha", 19);
Time taken: 0.637 seconds
spark-sql>

查询

spark-sql> SELECT name FROM people WHERE age IS NULL;
Michael
Time taken: 0.272 seconds, Fetched 1 row(s)

Beeline

Beeline 是通过 HiveServer2 来运行 HQL 查询数据。
启动 Thrift 服务
$SPARK_HOME下启动:

./sbin/start-thriftserver.sh

连接 Thrift 服务

./bin/beeline

连接成功后显示:

!connect jdbc:hive2://localhost:10000

查询

0: jdbc:hive2://localhost:10000> SHOW tables;+-----------+------------+--------------+
| database  | tableName  | isTemporary  |
+-----------+------------+--------------+
| default   | people     | false        |
+-----------+------------+--------------+
1 row selected (0.417 seconds)0: jdbc:hive2://localhost:10000> SELECT * FROM people;+-----------+-------+
|   name    |  age  |
+-----------+-------+
| Samantha  | 19    |
| Andy      | 30    |
| Michael   | NULL  |
+-----------+-------+
3 rows selected (1.512 seconds)0: jdbc:hive2://localhost:10000>

停止 Thrift 服务

./sbin/stop-thriftserver.sh

Tableau

和前两种类似,也需要先启动 Thrift 服务。
关于详细使用可以查看官方文档

外部数据源

可以通过 Spark SQL 查询外部数据源。

通过 JDBC 连接数据库

可以通过类似下边的方式访问数据库:

./bin/spark-shell --driver-class-path $database.jar --jars $database.jar

远程数据库将被加载为 DataFrame 或者 Spark SQL 临时视图。
下边是对一些连接参数的说明:

参数名称说明
user, password连接远程数据库的用户名和密码
url连接 url, 例如:jdbc:postgresql://localhost/test?user=fred&password=secret
dbtable需要操作的表。
query查询语句
driverURL 连接中 JDBC 驱动的类名

更多参数说明:官方文档

PostgreSQL

启动 pg JDBC jar 包:

bin/spark-shell --jars postgresql-42.2.6.jar

下边展示了如何通过 Spark SQL API 和 JDBC 访问:

// In Scala
// Read Option 1: Loading data from a JDBC source using load method
val jdbcDF1 = spark
.read
.format("jdbc")
.option("url", "jdbc:postgresql:[DBSERVER]")
.option("dbtable", "[SCHEMA].[TABLENAME]")
.option("user", "[USERNAME]")
.option("password", "[PASSWORD]")
.load()// Read Option 2: Loading data from a JDBC source using jdbc method
// Create connection properties
import java.util.Properties
val cxnProp = new Properties()
cxnProp.put("user", "[USERNAME]") 
cxnProp.put("password", "[PASSWORD]")// Load data using the connection properties
val jdbcDF2 = spark
.read
.jdbc("jdbc:postgresql:[DBSERVER]", "[SCHEMA].[TABLENAME]", cxnProp)// Write Option 1: Saving data to a JDBC source using save method
jdbcDF1
.write
.format("jdbc")
.option("url", "jdbc:postgresql:[DBSERVER]")
.option("dbtable", "[SCHEMA].[TABLENAME]")
.option("user", "[USERNAME]")
.option("password", "[PASSWORD]")
.save()// Write Option 2: Saving data to a JDBC source using jdbc method
jdbcDF2.write
.jdbc(s"jdbc:postgresql:[DBSERVER]", "[SCHEMA].[TABLENAME]", cxnProp)
And here’s how to do it in PySpark:

通过 PySpark:

# In Python
# Read Option 1: Loading data from a JDBC source using load method
jdbcDF1 = (spark.read.format("jdbc") .option("url", "jdbc:postgresql://[DBSERVER]").option("dbtable", "[SCHEMA].[TABLENAME]").option("user", "[USERNAME]").option("password", "[PASSWORD]").load())# Read Option 2: Loading data from a JDBC source using jdbc method
jdbcDF2 = (spark.read .jdbc("jdbc:postgresql://[DBSERVER]", "[SCHEMA].[TABLENAME]",properties={"user": "[USERNAME]", "password": "[PASSWORD]"}))# Write Option 1: Saving data to a JDBC source using save method
(jdbcDF1.write.format("jdbc").option("url", "jdbc:postgresql://[DBSERVER]").option("dbtable", "[SCHEMA].[TABLENAME]") .option("user", "[USERNAME]").option("password", "[PASSWORD]").save())# Write Option 2: Saving data to a JDBC source using jdbc method
(jdbcDF2.write .jdbc("jdbc:postgresql:[DBSERVER]", "[SCHEMA].[TABLENAME]",properties={"user": "[USERNAME]", "password": "[PASSWORD]"}))

MySQL

启动 Mysql JDBC jar 包:

bin/spark-shell --jars mysql-connector-java_8.0.16-bin.jar

通过 Scala 访问:

// In Scala
// Loading data from a JDBC source using load 
val jdbcDF = spark
.read
.format("jdbc")
.option("url", "jdbc:mysql://[DBSERVER]:3306/[DATABASE]")
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "[TABLENAME]")
.option("user", "[USERNAME]")
.option("password", "[PASSWORD]")
.load()// Saving data to a JDBC source using save 
jdbcDF
.write
.format("jdbc")
.option("url", "jdbc:mysql://[DBSERVER]:3306/[DATABASE]")
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "[TABLENAME]")
.option("user", "[USERNAME]")
.option("password", "[PASSWORD]")
.save()s

通过 PySpark 访问:

# In Python
# Loading data from a JDBC source using load 
jdbcDF = (spark.read.format("jdbc").option("url", "jdbc:mysql://[DBSERVER]:3306/[DATABASE]").option("driver", "com.mysql.jdbc.Driver") .option("dbtable", "[TABLENAME]").option("user", "[USERNAME]").option("password", "[PASSWORD]").load())# Saving data to a JDBC source using save 
(jdbcDF.write .format("jdbc") .option("url", "jdbc:mysql://[DBSERVER]:3306/[DATABASE]").option("driver", "com.mysql.jdbc.Driver") .option("dbtable", "[TABLENAME]") .option("user", "[USERNAME]").option("password", "[PASSWORD]").save())

还有一些其他外部数据源的连接使用说明:

  • Cassandra
  • Snowflake
  • MongoDB

高阶函数

当我们对复杂数据类型(多种简单数据类型嵌套)进行操作时,一般有两种方式:

  • 拆分成简单的数据类型操作,操作完后合并成复杂类型
  • 使用 UDF

Explode 和 Collect

-- In SQL
SELECT id, collect_list(value + 1) AS values
FROM  (SELECT id, EXPLODE(values) AS valueFROM table) x
GROUP BY id

EXPLODE 会为values中的每个元素(值)创建一个新的行(带有id)。
然后 collect_list() 会返回一个计算完的列表,需要注意的是 Group BY 需要 shuffle 操作,返回的结果可能并不是想要的顺序,而且 values 列表可能是一个数据很多的很宽的列表,因此计算所消耗的内存是昂贵的。

UDF

上边的查询可以通过 UDF 函数实现:

// In Scala
def addOne(values: Seq[Int]): Seq[Int] = {values.map(value => value + 1)
}
val plusOneInt = spark.udf.register("plusOneInt", addOne(_: Seq[Int]): Seq[Int])

sql 使用 UDF:

spark.sql("SELECT id, plusOneInt(values) AS values FROM table").show()

虽然使用UDF 返回的查询结果是有序的,但是需要经过序列化和反序列化,资源消耗也是昂贵的。

内置函数

我们可以使用内置高阶函数,进行复杂数据类型的操作,这些内置函数的开销比上边两种都小。
更多请查看官方文档

高阶函数

除了前面提到的内置函数之外,还有一些接受匿名lambda函数作为参数的高阶函数。下面是一个高阶函数的例子:

-- In SQL
transform(values, value -> lambda expression)

transform()函数接受一个数组(值)和一个匿名函数(lambda表达式)作为输入。该函数通过对每个元素应用匿名函数透明地创建一个新数组,然后将结果赋值给输出数组(类似于UDF方法,但效率更高)。

# In Python
from pyspark.sql.types import *
schema = StructType([StructField("celsius", ArrayType(IntegerType()))])t_list = [[35, 36, 32, 30, 40, 42, 38]], [[31, 32, 34, 55, 56]]
t_c = spark.createDataFrame(t_list, schema)
t_c.createOrReplaceTempView("tC")# Show the DataFrame
t_c.show()
// In Scala
// Create DataFrame with two rows of two arrays (tempc1, tempc2)
val t1 = Array(35, 36, 32, 30, 40, 42, 38)
val t2 = Array(31, 32, 34, 55, 56)
val tC = Seq(t1, t2).toDF("celsius")
tC.createOrReplaceTempView("tC")// Show the DataFrame
tC.show()

输出内容:

+--------------------+
|             celsius|
+--------------------+
|[35, 36, 32, 30, ...|
|[31, 32, 34, 55, 56]|
+--------------------+

transform()

transform(array<T>, function<T, U>): array<U>

transform()函数通过对输入数组的每个元素应用一个函数来生成一个数组(类似于map()函数):

// In Scala/Python
// Calculate Fahrenheit from Celsius for an array of temperatures
spark.sql("""
SELECT celsius, transform(celsius, t -> ((t * 9) div 5) + 32) as fahrenheit FROM tC
""").show()+--------------------+--------------------+
|             celsius|          fahrenheit|
+--------------------+--------------------+
|[35, 36, 32, 30, ...|[95, 96, 89, 86, ...|
|[31, 32, 34, 55, 56]|[87, 89, 93, 131,...|
+--------------------+--------------------+

filter()

filter(array<T>, function<T, Boolean>): array<T>

filter()函数的作用是:生成一个仅由输入数组中布尔函数为真的元素组成的数组:

// In Scala/Python
// Filter temperatures > 38C for array of temperatures
spark.sql("""
SELECT celsius, filter(celsius, t -> t > 38) as high FROM tC
""").show()+--------------------+--------+
|             celsius|    high|
+--------------------+--------+
|[35, 36, 32, 30, ...|[40, 42]|
|[31, 32, 34, 55, 56]|[55, 56]|
+--------------------+--------+

exists()

exists(array<T>, function<T, V, Boolean>): Boolean

exists()函数如果布尔函数对输入数组中的任何元素成立则返回true:

// In Scala/Python
// Is there a temperature of 38C in the array of temperatures
spark.sql("""
SELECT celsius, exists(celsius, t -> t = 38) as thresholdFROM tC
""").show()+--------------------+---------+
|             celsius|threshold|
+--------------------+---------+
|[35, 36, 32, 30, ...|     true|
|[31, 32, 34, 55, 56]|    false|
+--------------------+---------+

reduce()

reduce(array<T>, B, function<B, T, B>, function<B, R>)

reduce()函数通过使用函数<B, T, B>将数组元素合并到缓冲区B中,并在最后的缓冲区上应用结束函数<B, R>,将数组元素减少为单个值:

// In Scala/Python
// Calculate average temperature and convert to F
spark.sql("""
SELECT celsius, reduce(celsius, 0, (t, acc) -> t + acc, acc -> (acc div size(celsius) * 9 div 5) + 32) as avgFahrenheit FROM tC
""").show()+--------------------+-------------+
|             celsius|avgFahrenheit|
+--------------------+-------------+
|[35, 36, 32, 30, ...|           96|
|[31, 32, 34, 55, 56]|          105|
+--------------------+-------------+

常用 DataFrames 和 Spark SQL 操作

Spark SQL的部分强大功能来自于它支持的广泛的DataFrame操作(也称为无类型数据集操作)。操作列表相当广泛,包括:

  • 聚合函数
  • 集合函数
  • Datetime函数
  • 数学函数
  • 混合函数
  • 非聚合函数
  • 排序功能
  • 字符串函数
  • UDF 函数
  • 窗口函数

关于这些函数的具体使用可以查看官方文档

总结

本文探讨了Spark SQL如何与外部组件接口。我们讨论了创建用户定义函数,包括Pandas udf,并提供了一些执行Spark SQL查询的选项(包括Spark SQL shell、Beeline和Tableau)。然后,我们提供了如何使用Spark SQL连接各种外部数据源的示例,如SQL数据库,PostgreSQL, MySQL, Tableau, Azure Cosmos DB, MS SQL Server等。
我们探索了Spark用于复杂数据类型的内置函数,并给出了一些使用高阶函数的示例。最后,我们讨论了一些常见的关系操作符,并展示了如何执行DataFrame操作的选择。

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

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

相关文章

隐私计算实训营第九讲-隐语多方安全计算在安全核对的行业实践

隐私计算实训营第九讲-隐语多方安全计算在安全核对的行业实践 文章目录 隐私计算实训营第九讲-隐语多方安全计算在安全核对的行业实践1.业务背景&#xff1a;安全核对产生的土壤1.1相关政策出台1.2 数据差异的来源 2.产品方案&#xff1a;从试点到规模化的路3.技术共建&#xf…

如何用MATLAB进行核密度估计

核密度估计&#xff08;Kernel Density Estimation&#xff0c;KDE&#xff09;是一种用于估计概率密度函数的非参数方法。以下是核密度估计的基本步骤和公式&#xff1a; 步骤&#xff1a; (1)数据预处理&#xff1a;在进行核密度估计之前&#xff0c;需要对原始数据进行清洗…

微信小程序报错——“errno“: 600001, “errMsg“: “request:fail -2:net::ERR_FAILED“

bug现象 微信小程序体验版和真机调试 进入小程序的时候接口就出现了这个报错 "errno": 600001, "errMsg": "request:fail -2:net::ERR_FAILED" 排查 检查是证书过期还是证书链不完整 证书的信任链完整问题&#xff0c;可以在 亚数信息-SSL/TLS安…

web安全学习笔记(8)

记一下第十二节课的内容。 一、PHP文件包含的四种方式 Include和Include_once 操作系统会读取包含的文件的内容&#xff0c;并将它插入主文件中&#xff0c;include方式的文件包含会在包含失败的情况下输出警告信息&#xff0c;而include_once方式会检查包含的文件是否已经被…

口语教育的黄金时代:AI技术引领教育创新与创业机遇

这些人的赚钱思路是真灵活&#xff01; 这几天刷到艾维奇采访之昊的视频&#xff0c;做口语教育真赚钱&#xff0c;lv的包包随便买&#xff0c;住大房子&#xff0c;三辆车&#xff0c;有评论晒图一个九百的课&#xff0c;卖了1.3万份&#xff0c;直接千万到账。 然后我又想到…

TCP重传机制总结

超时重传概念 超时重传&#xff1a;发送方每发送一个数据包&#xff0c;就会为这个数据包设置一个超时时间&#xff0c;如果在时间内没收到应答这个数据包的ACK包&#xff0c;需要重新发送这个数据包&#xff1b;每次重传后&#xff0c;RTO会成倍增加&#xff0c;且重传次数有…

python-pytorch实现skip-gram 0.5.000【直接可运行】

python-pytorch实现skip-gram 0.5.000【直接可运行】 参考导入包加载数据和切词获取wordList、raw_text获取vocab、vocab_sizeword_to_idx、idx_to_word准备训练数据准备模型和参数训练模型保存模型简单预测获取训练后的词向量画图看下分布利用词向量计算相似度余弦点积 参考 …

Jmeter —— 自动录制脚本

1、Jmeter配置 1.1新增一个线程组 1.2Jmeter中添加HTTP代理 1.3配置HTTP代理服务器 修改端口 修改Target Cintroller(目标控制器) 修改Grouping(分组) 编辑录制中的包含和排除 在“URL Patterns to include包含模式”中填入.*(123456).*用以过滤请求地址中不包含123456的请求…

【K8S:初始化】:执行kubeadm显示:connection refused.

文章目录 [root10 kubernetes]# kubeadm init --kubernetes-versionv1.23.0 --image-repositoryregistry.aliyuncs.com/google_containers --apiserver-advertise-address192.168.56.104 [init] Using Kubernetes version: v1.23.0 [preflight] Running pre-flight checks [pre…

Angular Web项目前端无法正确显示base64类型的图片

昨天在本地环境部署网站时遇见了一个问题&#xff0c;后端接口返回的Base64类型的图片文件&#xff0c;在浏览器页面上无法正常显示&#xff0c;经过一番排查发现&#xff0c;问题出现在了两个方面&#xff1a; 1、网站前端使用了Angular框架&#xff0c;Angular中默认将所有输…

深入浅出 useEffect:React 函数组件中的副作用处理详解

useEffect 是 React 中的一个钩子函数&#xff0c;用于处理函数组件中的副作用操作&#xff0c;如发送网络请求、订阅消息、手动修改 DOM 等。下面是 useEffect 的用法总结&#xff1a; 基本用法 import React, { useState, useEffect } from react;function Example() {cons…

使用UDP完成网络单词查询,利用dict数据库

【注】UDP的优缺点&#xff1a; 1&#xff1a;传输效率高 2&#xff1a;易出现数据丢失 3&#xff1a;以数据报的形式传输 思路&#xff1a; step1&#xff1a;获取客户端请求 step2&#xff1a;查询单词 step3&#xff1a;响应客户端 Client.py from socket import *SERVICE_…

Datacom HCIP笔记-MPLS协议 之二

在Ingress节点执行该命令时&#xff0c;触发所有的32位路由建立LDPLSP。 在Egress节点执行该命令时&#xff0c;触发本地32位路由建立LDPLSP&#xff0c; egress就是主机路由始发路由器 ingress就是主机路由非始发路由器 默认情况下&#xff1a;华为路由器仅为非物理接口主机路…

【C++11】initializer_list | 右值引用 | 完美转发

一切皆可列表{ }初始化 在C98,允许花括号{ } 对数组、结构体类型初始化。 class Data { public:Data(int y, int m, int d):_y(y), _m(m), _d(d){} private:int _y;int _m;int _d; };int arr[4]{0,1,2,3};//列表初始化 Data d1{2024,03,21};//列表初始化 C11允许通过{ } 初始化…

云数据库价格一瞥(华为云、百度智能云、腾讯云、阿里云)

最近&#xff0c;大家似乎和价格“磕”上了。本文仅考虑主流产品&#xff08; RDS MySQL、Redis &#xff09;的部分主流规格&#xff0c;对各家厂商的价格做一个对比&#xff0c;供参考。 TL;DR&#xff1a; 总体来看&#xff0c;各家云厂商价格趋于持平&#xff0c;部分主流商…

创建一个qt登录界面,密码账号正确转到窗口2,否则弹出对话框提示账号密码错误,窗口2有四个按键,三个按键可以朗读按键文本,第四个退出。

作业要求&#xff1a; 主函数&#xff1a; int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();Form1 f;//连接窗口1的信号函数和窗口2打开的lambda函数Widget::connect(&w,&Widget::login,[&](){f.show();});return a.exec(); }窗…

无影云电脑不能连接到本机的调试串口的解决方案

目录 概述 解决方案 云端电脑中的操作 本地USBDK驱动程序的更新 概述 我从1月份开始使用阿里的无影云电脑进行嵌入式开发板的测试&#xff0c;主要的原因有两个&#xff1a;一是平时使用的笔记本资源过于紧张&#xff0c;二是方便移动办公&#xff0c;这样我只要平时拿着开…

Android 在xml 布局中如何嵌套 Jetpack Compose

最近在项目开发的过程中需要用到 Jetpack Compose&#xff0c;之前没有接触过Compose&#xff0c;所以项目一直没有用到Compose。通过查看官网发现Compose上手比较快&#xff0c;但是准备比较复杂的布局要转换成Compose 不是一件容易的事情。那有没有可能只是对成熟的项目中的x…

解锁阿里巴巴1688数据宝藏:API助力批量获取商品价格、标题、图片及库存

在数字化时代&#xff0c;数据已成为商业决策的重要依据。对于电商从业者来说&#xff0c;掌握商品的价格、标题、图片及库存等关键信息&#xff0c;是优化销售策略、提升竞争力的关键。阿里巴巴1688平台作为国内领先的B2B电商平台&#xff0c;其海量的商品数据为商家提供了丰富…

【机器学习300问】63、如何区分二分类、多分类和多标签分类?

在机器学习中&#xff0c;分类是指根据一系列特征将实例数据划分到预先定义的类别或者标签的监督学习任务。分类任务按照类别数量区分&#xff0c;可以细分为&#xff1a; 一、二分类&#xff08;Binary classification&#xff09; 二分类只有两个类别的分类&#xff0c;例如…