掌握 gRPC:从安装到构建第一个C++ 和Python微服务

文章目录

  • 一、前言
    • 1. gRPC的概念和用途
    • 2. gRPC的优势
    • 3. gRPC的应用场景
  • 二、gRPC的基本原理
    • 1. RPC(远程过程调用)简介
    • 2. Protocol Buffers的作用
    • 3. gRPC与传统HTTP/REST服务的比较
  • 三、安装gRPC
    • 1. 系统要求和前置条件
    • 2. 安装步骤概述
  • 四、创建第一个gRPC c++项目
    • 1. 设置项目结构
    • 2. 定义服务和消息
    • 3. 生成服务代码
    • 4. 实现gRPC服务端
    • 5. 实现gRPC客户端
    • 6. 创建Makefile并编译运行
  • 五、创建一个gRPC python项目
    • 1. 设置项目结构
    • 2. 定义服务和消息
    • 3. 生成服务代码
    • 4. 实现gRPC服务端
    • 5. 实现gRPC客户端
  • 六、总结
  • 七、参考资料


一、前言

1. gRPC的概念和用途

在现代软件开发中,gRPC已经成为一个重要的通信框架。作为一个由Google开发并维护的开源项目,gRPC允许不同的服务和应用之间进行有效的远程过程调用(RPC)。它基于HTTP/2协议,不仅提高了通信的效率,还简化了跨语言服务的互操作性。gRPC使用Protocol Buffers作为其接口定义语言,这是一种语言中立的、平台中立的接口描述语言,用于序列化结构化数据。
gRPC的用途广泛,从微服务架构中的服务间通信到支持移动应用和浏览器客户端的后端服务。它的设计使其非常适合于构建分布式系统和云服务,尤其是在需要高效、低延迟通信的场景中。

2. gRPC的优势

gRPC之所以在现代应用开发中受到青睐,主要归功于它的几个关键优势。

  1. 首先,它基于HTTP/2,这不仅意味着更高的性能,还包括了对多路复用、服务器推送等现代网络技术的支持。这使得gRPC在处理大量并发请求时表现出色,同时减少了通信过程中的延迟。
  2. 其次,gRPC的跨平台和跨语言支持极大地简化了不同服务和应用之间的集成。无论是C++、Java、Python还是任何其他支持的语言,gRPC都能确保不同语言编写的服务可以无缝交互。
  3. 此外,gRPC通过使用Protocol Buffers,提供了一种强类型的接口定义方式。这不仅使得服务间的通信更加清晰,还提高了数据传输的效率。与此同时,gRPC支持双向流和流控制,允许在一个持久连接中进行双向通信,这对于构建实时交互应用来说是一个巨大的优势。

3. gRPC的应用场景

gRPC适用于多种应用场景,特别是那些需要高效、可靠通信的场景。在微服务架构中,gRPC常被用于服务之间的通信,提供了一种比传统HTTP RESTful API更高效的方法。此外,它也被广泛用于构建API,特别是那些需要支持多种语言客户端的API。
在云计算和分布式系统领域,gRPC的高效性和低延迟特性使其成为组件间通信的理想选择。同时,在物联网(IoT)领域,gRPC因其轻量级和高效性而被用于设备间的通信。

总的来说,gRPC凭借其高性能、跨语言支持和强类型接口,已经成为现代软件开发中不可或缺的一部分。


二、gRPC的基本原理

1. RPC(远程过程调用)简介

远程过程调用(RPC)是一种使得在不同计算机环境中运行的程序能够相互调用函数或方法的技术。简而言之,RPC允许一台计算机上的程序调用另一台计算机上的程序,就像调用本地程序一样,而无需关心底层网络技术的细节。RPC抽象了网络通信的复杂性,使开发者能够专注于业务逻辑的实现,而不是通信细节。

2. Protocol Buffers的作用

Protocol Buffers,简称Protobuf,是由Google开发的一种语言无关、平台无关的序列化框架。它用于序列化结构化数据,类似于XML或JSON,但更小、更快、更简单。在gRPC中,Protobuf用作接口定义语言(IDL),用于定义服务接口和消息格式。
Protobuf的主要优势包括:

  • 高效的编码:生成的数据非常紧凑,这使得它在网络传输中非常高效。
  • 跨语言支持:支持多种编程语言,包括Java、C++、Python等。
  • 清晰的结构定义:使用.proto文件定义数据结构,使得数据模型在不同的服务和应用之间清晰且一致。
  • 向后兼容性:可以在不破坏已部署程序的情况下更新数据结构。

3. gRPC与传统HTTP/REST服务的比较

gRPC和传统的HTTP/REST服务在多个方面有显著的不同:

  1. 传输协议:
  • gRPC基于HTTP/2,支持双向流、多路复用、服务器推送等特性,这使得gRPC在性能上优于基于HTTP/1.1的REST服务。
  • HTTP/REST服务通常使用HTTP/1.1,每个请求/响应循环都需要一个新的TCP连接,这可能导致更高的延迟。
  1. 数据格式:
  • gRPC使用Protobuf作为数据交换格式,这是一种二进制格式,更加高效。
  • 传统的REST服务通常使用JSON或XML,这些是文本格式,相比于Protobuf,它们更加冗长,解析速度也更慢。
  1. API设计:
  • gRPC更倾向于使用严格定义的Protobuf来描述服务接口,这提供了更强的类型检查和结构清晰性。
  • REST则更灵活,可以使用不同的URL和HTTP方法(如GET、POST)来描述操作,但这可能导致API的不一致性。
  1. 流控制:
  • gRPC原生支持流控制,允许在单个连接中发送连续的消息流。
  • 在REST中实现流通常更复杂,通常需要使用WebSockets或长轮询等技术。
    总体而言,gRPC提供了一种更高效、更严格、更适合高性能需求的通信方式,特别是在微服务和分布式系统中。而HTTP/REST服务则在简单性和通用性方面有优势,更适合公共API和Web应用程序。

三、安装gRPC

参考grpc官网

1. 系统要求和前置条件

在开始安装gRPC之前,确保您的系统满足以下要求:

操作系统:Linux(如Ubuntu)、macOS 或 Windows。
编译工具:如gcc、g++(对于Linux/macOS)或 Visual Studio(对于Windows)。
Git:用于克隆gRPC仓库。
Python:如果打算使用Python版本的gRPC。
其他依赖:如autoconf、libtool、pkg-config等。

2. 安装步骤概述

安装gRPC涉及以下几个主要步骤:
安装依赖项。
克隆gRPC仓库。
编译和安装gRPC。
安装gRPC C++插件。
安装Protocol Buffers编译器。
(可选)安装Python版本的gRPC。

  1. 安装高级版本的cmake
    安装使用gprc最低版本为3.15,目前使用sudo apt install cmake得到的只有3.10,因此要卸载掉旧版本的cmake,源码编译高版本的。具体方法参考cmake github网站,这里不详述。
  2. 安装依赖项
    在Linux系统(如Ubuntu)上,可以使用以下命令安装必要的依赖,常安装类似的库的可以忽略:
sudo apt update
sudo apt install build-essential autoconf libtool pkg-config
  1. 克隆gRPC仓库
    使用Git克隆gRPC的GitHub仓库:
  • 下载源码
git clone  https://github.com/grpc/grpc
  • 查看版本并选择合适的版本,这里选择v1.45.2相对较新的版本
git tag
git checkout v1.45.2
  • 下载第三方依赖库,下载完后会发现整个grpc目录内容明显变大
git submodule update --init
  1. 编译和安装
MY_INSTALL_DIR=$HOME/.local
echo $MY_INSTALL_DIR
cd grpc
mkdir -p cmake/build
pushd cmake/build
cmake -DgRPC_INSTALL=ON \-DgRPC_BUILD_TESTS=OFF \-DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \../..
make -j $(nproc) 
sudo make install
popd

特别说明一下,官网不建议直接安装在/usr/local里,怕不好卸载,所有选择$HOME/.local

  1. protobuf安装
    不用手动安装protobuf,不然版本可能和grcp不匹配,必须在 grpc 执行 git submodule update --init 命令之后生成的 third_party/protobuf 里面编译安装对应的 protobuf。
cd third_party/protobuf/
./autogen.sh 
./configure --prefix=$HOME/.local # 路径选择之前安装grpc的路径
makesudo make install
sudo ldconfig  # 使得新安装的动态库能被加载protoc --version
# 显示3.19.4
  1. 安装Python版本的gRPC
    如果打算在Python项目中使用gRPC,可以通过pip安装:
pip install grpcio

为了生成Python的gRPC代码,还需要安装gRPC的Python插件:

pip install grpcio-tools

完成以上步骤后,应该已经成功在系统上安装了gRPC及其相关工具。


四、创建第一个gRPC c++项目

1. 设置项目结构

一个基本的gRPC项目通常包括服务定义(Protocol Buffers)、服务端实现和客户端实现。以下是一个C++项目的示例结构:

grpc-example/
│
├── protos/
│   └── my_service.proto
│
├── servers/
│   └── server.cpp
│
└── clients/└── client.cpp
  • protos/ 目录包含所有 .proto 文件,定义了gRPC服务和消息格式。
  • server/ 目录包含服务端的实现代码。
  • client/ 目录包含客户端的实现代码。
    编写Protocol Buffers文件
    在 protos/ 目录下创建一个 .proto 文件,如 my_service.proto。

2. 定义服务和消息

syntax = "proto3";package myservice;// 定义一个简单的消息
message MyRequest {string name = 1;
}message MyResponse {string greeting = 1;
}// 定义服务
service MyService {// 定义一个RPC方法rpc SayHello (MyRequest) returns (MyResponse);
}

3. 生成服务代码

  • 修改环境变量
export PATH=$HOME/.local/bin/:$PATH
  • 使用 protoc 编译器生成C++服务代码:
protoc -I protos/ protos/my_service.proto --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin`

这将在相应的目录中生成C++代码。

我们为了项目的需要,将cc文件改为cpp文件,生成的文件复制到protos目录下

4. 实现gRPC服务端

在 servers/ 目录下创建 server.cpp。
实现 .proto 文件中定义的服务接口。例如:

#include <grpcpp/grpcpp.h>
#include "my_service.grpc.pb.h"using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using myservice::MyRequest;
using myservice::MyResponse;
using myservice::MyService;// 实现服务类
class MyServiceImpl final : public MyService::Service {Status SayHello(ServerContext* context, const MyRequest* request,MyResponse* reply) override {std::string prefix("Hello ");reply->set_greeting(prefix + request->name());return Status::OK;}
};void RunServer() {std::string server_address("0.0.0.0:50051");MyServiceImpl service;ServerBuilder builder;builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());builder.RegisterService(&service);std::unique_ptr<Server> server(builder.BuildAndStart());std::cout << "Server listening on " << server_address << std::endl;server->Wait();
}int main(int argc, char** argv) {RunServer();return 0;
}

5. 实现gRPC客户端

在 clients/ 目录下创建 client.cpp。

实现代码以调用服务端的RPC方法。例如:

#include <grpcpp/grpcpp.h>
#include "my_service.grpc.pb.h"using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using myservice::MyRequest;
using myservice::MyResponse;
using myservice::MyService;class MyClient {public:MyClient(std::shared_ptr<Channel> channel): stub_(MyService::NewStub(channel)) {}std::string SayHello(const std::string& user) {MyRequest request;request.set_name(user);MyResponse reply;ClientContext context;Status status = stub_->SayHello(&context, request, &reply);if (status.ok()) {return reply.greeting();} else {std::cout << status.error_code() << ": " << status.error_message()<< std::endl;return "RPC failed";}}private:std::unique_ptr<MyService::Stub> stub_;
};int main(int argc, char** argv) {MyClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));std::string user("World");std::string reply = client.SayHello(user);std::cout << "Client received: " << reply << std::endl;return 0;
}

6. 创建Makefile并编译运行

  • 根据上面的工程创建一个Makefile
CXX = g++
CXXFLAGS = -std=c++14 -g -O0 -I/home/ai/.local/include -Iinclude
LDFLAGS = -L/home/ai/.local/lib `pkg-config --libs grpc++ grpc`\-lgrpc++_reflection\-lprotobuf -lpthread -ldlPROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`PROTOS_PATH = protos
OBJS_PATH = objsvpath %.proto $(PROTOS_PATH)
vpath %.cpp servers:clients:$(PROTOS_PATH)all: server clientserver: $(OBJS_PATH)/my_service.pb.o $(OBJS_PATH)/my_service.grpc.pb.o $(OBJS_PATH)/server.o$(CXX) $^ $(LDFLAGS) -o $@client: $(OBJS_PATH)/my_service.pb.o $(OBJS_PATH)/my_service.grpc.pb.o $(OBJS_PATH)/client.o$(CXX) $^ $(LDFLAGS) -o $@$(OBJS_PATH)/%.o: %.cpp$(CXX) $(CXXFLAGS) -c $< -o $@clean:rm -f $(OBJS_PATH)/*.o server client
  • 修改环境变量
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH 

下面就可以正常的编译运行了。

完成以上步骤后,gRPC项目基本结构就搭建好了。可以编译并运行服务端代码,然后编译并运行客户端代码来测试RPC方法的调用。


五、创建一个gRPC python项目

1. 设置项目结构

同上一节c++项目

2. 定义服务和消息

同上一节c++项目

3. 生成服务代码

使用 protoc 编译器生成服务代码。根据您使用的编程语言,命令会有所不同。例如,对于Python:

python -m grpc_tools.protoc -I protos/ protos/my_service.proto --python_out=. --grpc_python_out=.

这将在相应的目录中生成Python代码。

4. 实现gRPC服务端

创建服务端代码文件server.py。

from concurrent import futures
import grpc
import my_service_pb2
import my_service_pb2_grpcclass MyServiceServicer(my_service_pb2_grpc.MyServiceServicer):def SayHello(self, request, context):response = my_service_pb2.MyResponse()response.greeting = 'Hello, ' + request.namereturn responsedef serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))my_service_pb2_grpc.add_MyServiceServicer_to_server(MyServiceServicer(), server)server.add_insecure_port('[::]:50051')server.start()server.wait_for_termination()if __name__ == '__main__':serve()

5. 实现gRPC客户端

在 client/ 目录下创建客户端代码文件。

实现代码以调用服务端的RPC方法。例如,使用Python:

import grpc
import my_service_pb2
import my_service_pb2_grpcdef run():with grpc.insecure_channel('localhost:50051') as channel:stub = my_service_pb2_grpc.MyServiceStub(channel)response = stub.SayHello(my_service_pb2.MyRequest(name='World'))print("Client received: " + response.greeting)if __name__ == '__main__':run()

完成以上步骤后,python gRPC项目基本结构就搭建好了。可以运行服务端代码,然后运行客户端代码来测试RPC方法的调用。


六、总结

在本系列文章中,我们深入探讨了 gRPC 的基本概念、安装步骤以及如何在 C++ 和 Python 项目中实际应用 gRPC。从 gRPC 的基础出发,我们首先介绍了其与传统通信框架的比较,突出了 gRPC 在现代应用程序中提供的高效和可靠的 RPC 解决方案。

我们详细讨论了 gRPC 的安装过程,包括在不同操作系统上的安装指南和潜在的挑战。这为读者提供了一个坚实的基础,以便在自己的开发环境中顺利部署 gRPC。

接着,文章重点介绍了如何在 C++ 和 Python 项目中使用 gRPC。通过具体的项目案例,我们展示了在这两种语言中编写、编译和运行 gRPC 服务端和客户端的步骤。这些案例不仅提供了实际的代码示例,还讲解了如何在项目中有效地应用 gRPC,从而使读者能够更好地理解和运用这一技术。

总体而言,本系列文章旨在提供一个全面的 gRPC 学习指南,从基本概念到实际应用,特别是在 C++ 和 Python 项目中的应用。通过这些内容,读者可以获得必要的知识和技能,以在自己的项目中有效地利用 gRPC,实现高效和可靠的服务间通信。


七、参考资料

  • grpc官网
  • grpc官方github

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

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

相关文章

单元测试、系统测试、集成测试知识总结

一、单元测试的概念 单元测试是对软件基本组成单元进行的测试&#xff0c;如函数或一个类的方法。当然这里的基本单元不仅仅指的是一个函数或者方法&#xff0c;有可能对应多个程序文件中的一组函数。 单元也具有一些基本的属性。比如&#xff1a;明确的功能、规格定义&#…

【python爬虫】设计自己的爬虫 4. 封装模拟浏览器 PyppeteerSimulate

Pyppeteer是Puppeteer的Python版实现 Pyppeteer的背后实际上有一个类似于Chrome的浏览器–Chromium class PyppeteerSimulate(BrowserSimulateBase):def __init__(self):self.browser Noneself.page None# 启动浏览器# is_headless 是否开启无头模式# is_cdp 是否使用cdp (C…

win10报错“api-ms-win-crt-string-l1-1-0.dll文件丢失,软件无法启动”,快速修复方法,亲测有效

api-ms-win-crt-string-l1-1-0.dll是Windows操作系统中的一个动态链接库文件&#xff0c;属于Microsoft C Runtime Library。它包含了Windows操作系统需要运行C程序的一些基本系统函数&#xff0c;比如字符串处理、内存分配等。 它的作用主要是提供一些基本的、用于支持C语言编…

go语言gin框架的基本使用

1.首先在linux环境上安装go环境&#xff0c;这个网上搜搜就行 2.初始化一个go mod&#xff0c;网上搜搜怎么初始化 3.下面go代码的网址和端口绑定自己本机的就行 4.与另一篇CSDN一起食用&#xff0c;效果更好哟---> libcurl的get、post的使用-CSDN博客 package mainimpo…

算法每日一题: 被列覆盖的最多行数 | 二进制 - 状态压缩

大家好&#xff0c;我是星恒 今天的题目又是一道有关二进制的题目&#xff0c;有我们之前做的那道 参加考试的最大学生数的 感觉&#xff0c;哈哈&#xff0c;当然&#xff0c;比那道题简单多了&#xff0c;这道题感觉主要的考点就是二进制&#xff0c;大家可以好好总结一下这道…

04、Kafka ------ CMAK 各个功能的作用解释(Cluster、集群、Broker、位移主题、复制因子、领导者副本、主题)

目录 启动命令&#xff1a;CMAK的用法★ 在CMAK中添加 Cluster★ 在CMAK中查看指定集群★ 在CMAK中查看 Broker★ 位移主题★ 复制因子★ 领导者副本和追随者副本★ 查看主题 启动命令&#xff1a; 1、启动 zookeeper 服务器端 小黑窗输入命令&#xff1a; zkServer 2、启动 …

苹果电脑Markdown写作工具:ulysses mac软件介绍

ulysses for mac是一款Markdown写作工具&#xff0c;支持Markdown拼写检查、语音识别、iCloud同步、版本管理等功能&#xff0c;并且可以导出为 PDF、word、RTF、TXT、Markdown、HTML 和 ePub等文件格式。 ulysses for mac软件介绍 适用于Mac&#xff0c;iPad和iPhone的终极写…

试除法判定质数算法总结

知识概览 质数的定义 在大于1的整数中&#xff0c;如果只包含1和本身这两个约数&#xff0c;就被称为质数&#xff0c;或者叫素数。 质数的判定——试除法 暴力算法 时间复杂度 改进算法 时间复杂度 暴力算法&#xff1a;时间复杂度O(n) 算法模版 bool is_pr…

简单几步使用Spring整合MyBatis(含配置多数据源和多Mapper XML文件路径)

1. 逻辑梳理 我们先分析下使用者视角&#xff1a;代码中使用Mapper接口对数据进行数据库操作&#xff0c;具体的SQL在Mapper xml文件中。可以看到Mapper接口和Mapper xml是有一定的关联关系的&#xff0c;我们的配置思路也是如此&#xff0c;就是把两者绑定起来即可。 首先我…

Idea live template

1:打印入参日志的配置 log.info("$methodName$ 方法入参: $argsLog$",$argsJson$); methodName:methodName() argsLog:groovyScript( "def result; def params\"${_1}\".replaceAll([\\\\[|\\\\]|\\\\s], ).split(,).toList(); for(i 0; i <…

【负载均衡oj】(七)ojserver

一.目的 负责负载均衡&#xff0c;获取网站首页&#xff0c;通过网络罗调用编译并运行并提供结果给用户。根据用户的操作提供不同的功能。采用mvc结构。使用 ctemplate文字模板做数据渲染 m在这里指的是和数据的交互&#xff0c;可以用文件或者sql交互。在使用文件的情况下&a…

CISP-DSG和CDGA该如何选择?

同样是数据治理&#xff0c;CDGA证书和CISP-DSG证书&#xff0c;它们之间有什么区别和各自的优势呢❓ 1️⃣CISP-DSG CISP-DSG证书聚焦于信息an全领域&#xff0c;特别guan注数据an全治理。 国际知名zi询机构Gartner用“风暴之眼”比喻“数据an全治理”&#xff0c;&#x1f44…

hyperf 基础合集

目前合计不包括数据库。 hyperf 一、搭建 -CSDN博客hyperf 二、路由 -CSDN博客hyperf 三、中间件 -CSDN博客hyperf 四、控制器 -CSDN博客hypef 五、请求及响应 -CSDN博客hyperf 六、异常处理 -CSDN博客hypef 七、配置文件的使用_-CSDN博客hypef 八、缓存 -CSDN博客hypef 九、日…

【机器学习】线性回归·可运行源码

一&#xff0c;基础函数库 import numpy as np from utils.features import prepare_for_trainingclass LinearRegression:def __init__(self, data, labels, polynomial_degree0, sinusoid_degree0, normalize_dataTrue):"""1.对数据进行预处理操作2.先得到所…

ssm基于java web 的QQ村旅游网站的设计+vue论文

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统旅游信息管理难度大&#xff0c;容错率低&#xff0c;管理…

el-select下拉框 change事件返回该项所有数据

主要代码 value-key <template><div><el-selectv-model"value"value-key"label"placeholder"请选择"change"selectChange"><el-optionv-for"item in options":key"item.label":label"…

云计算历年题整理

第一大题 第一大题计算 给出计算连接到EC2节点的EBS的高可用性(HA)的数学公式&#xff0c;如场景中所述&#xff1b;计算EC2节点上的EBS的高可用性(HA)&#xff1b;场景中80%的AWS EC2节点用于并行处理&#xff0c;总共有100个虚拟中央处理单元(vCPUs)用于处理数据&#xff0…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)在EventLoop的任务队列中添加新任务

任务队列是一个链表&#xff0c;每个节点包含channel类型、文件描述符和操作类型。在添加节点时&#xff0c;需要考虑线程同步&#xff0c;并确保节点被正确地添加到链表中。节点的操作可以写到另一个函数中&#xff0c;以便于程序的维护。在添加任务节点时&#xff0c;需要加互…

迅为RK3588开发板使用 FFMpeg 进行推流

Debian/Ubuntu 系统使用以下命令安装 FFMpeg &#xff0c;如下图所示&#xff1a; apt-get install ffmpeg 使用 ifconfig 查看开发板 ip 为 192.168.1.245 如下图所示&#xff1a; 使用 FFMpeg 推流一个 mp4 视频进行测试&#xff0c;作者将测试视频 test.mp4 放在了根目录下…

轻松入门:Anaconda 在 PyCharm 中的配置与应用指南

1 Anaconda Anaconda 和 Conda 是两个相关但不同的概念。 Anaconda 是一个免费且开源的发行版&#xff0c;包含了 Python 和 R 语言的数据科学和机器学习相关的众多包&#xff0c;它包括 Conda、Python、Jupyter Notebook 等多个科学计算和数据科学中常用的应用。 Anaconda 通过…