十年python程序员,初次尝试rust:“非常优秀!”

CSDN云计算 CSDN云计算     2022-12-13     226

关键词:

摘要:Python 和 Rust,都是近几年深受开发者喜爱的编程语言,那么作为一个拥有十年 Python 编程经验的开发者来说,初次尝试 Rust 会有怎样的感受呢?

链接:https://karimjedda.com/carefully-exploring-rust/

声明:本文为 CSDN 翻译,未经允许禁止转载。

作者 | Karim Jedda       

译者 | 弯月    责编 | 郑丽媛

出品 | CSDN(ID:CSDNnews)

最近,我找到了一份新工作,公司最常用的编程语言之一是 Rust。

在此之前,我使用 Python 长达十年之久,主要是做数据工程的工作。但如今,我打算尝试一下这种新的(对我来说)编程语言。我经常在不同平台上看到各类夸赞 Rust 的文章,我想看看 Rust 是否真的不负盛名。

Rust 与 Python 有很大的不同,因此我不打算在本文中详细说明 Rust 的独特之处。作为初学者,我只希望尽快上手,希望能以最短的过渡,尽快用 Rust 完成工作,同时也希望评估一下我自己的学习能力。

从某种程度上来说,我更感兴趣的是 Rust 整体的使用体验,而不是具体的功能列表。

设置开发环境

设置开发环境非常简单,只需参照 Rust 网站提供的示例,在终端中运行一个命令就可以了。

当你认为一切都已安装并配置妥当,此时如果想验证 Rust 是否已正确安装,只需在空目录中创建一个空项目:

cargo new tutorial
cd tutorial
cargo run

接下来,在文本编辑器中打开该文件夹。如果你是新手,我推荐 VSCode,因为其中的一些扩展很有帮助,关于如何使用这些扩展的指南也很容易入手。我推荐 rust-analyzer 作为 VSCode 的唯一扩展。

输出与调试

如果想了解程序是如何运行的,首先要做的就是通过命令行来了解程序在干什么,以及完成了什么。

此外,你还可以使用常规调试器。在 M1 上,我推荐在 Visual Studio Code 中使用 LLDB,它不仅工作良好,通常还要比在输出结果中打印日志更为方便。

到这里为止,Rust 与 Python 其实都非常相似,只不过所有命令都是通过 cargo run 运行的,而不是调用特定文件,如 python3 somefile.py。

另外,你也可以先运行 cargo build,然后运行 target/debug/tutorial 中的文件,得到的结果是相同的。接下来,如果将生成的文件复制到另一个位置或另一台类似的机器上,也可以正常工作,且无需安装任何与 Rust 相关的东西。

错误处理

不得不承认,编程中总会遇到一些意外,能够以可预测的方式处理这些意外非常重要。编程中的一大挑战就是很难考虑到程序中所有可能出现的错误,因为只要写代码就可能会出错。

“每个人都知道调试比编写程序要难一倍。所以,如果你在代码编写代码时就用尽了聪明才智,又如何调试呢?”

—— Brian W. Kernighan

在 Python 中,通常我们通过 try/except 方法来抛异常,并完成错误处理。我们运行一段代码,如果出错,则通过条件来捕捉异常,如果所有条件都不匹配,则将其放入一个通用的异常中。异常有各种不同的类别,Python 允许你在包中调用不存在的函数,并在运行时产生异常,但在 Rust 中这样做甚至无法通过编译——Rust 不允许在运行时出现任何奇怪的错误,从而消除了一大类不太容易预测的错误。

下面通过一个例子来说明 Rust 的这种方法,同时我会用 Python 的术语进行解释。

在上面的代码中,我们创建了一个自定义的异常,在 do_something 函数中抛出,而 main 函数会检查该异常。上面的代码跟 try/exept 基本上一样,只不过多了一些样板代码(这些样板代码是必须的,但以我现在的水平有点难以理解)。

你也许会说“肯定有更好的办法”,特别是如果你有很多 Python 经验的话,的确如此,我们将不得不使用包。

使用外部包

与其他行业相比,编程的最大优势就是可以使用别人构建的东西。如果你计划在程序中进行错误处理,那么有一个很好用的包 thiserror。Rust 的包管理器是 cargo。

Rust 中的包叫做 crate。安装方法为编辑目录下的 Cargo.toml 文件。在本例中,我们在 [dependencies] 后面添加 thiserror = "1.0" 就可以了。

然后可以像下面这样重写之前的代码:

现在代码看起来很正常。与一切从头开始相比,我更喜欢这种做法。

我花了四五年时间才找到用 Python 编程的乐趣,所以我也愿意多花些时间来探索 Rust 的高级功能。Rust 有许多错误处理的方法,而我喜欢更简单的方法。

我有意略过了一些简单的概念,比如“什么是 enum?” “pub 是什么意思?” “那些#标记是什么”等,因为你只需运行一下代码就能明白它们的意思。

一切看起来都还不错。那么,测试方面又如何呢?

编写测试

测试应该从单元测试和集成测试两个级别上着手。实现方法有好几种,虽然你可以把测试代码和 Rust 代码放在同一个文件中(这也是官方指南的推荐),但我还是希望用一个单独的文件夹来组织所有测试代码,这样可以减少阅读代码时的负担,也可以减少编辑文件时占用的屏幕面积。而且说实话,在编写测试和编写代码时,我的心情是不一样的。

方法之一如下:

然后可以用 cargo test 运行测试,结果如下:

还有许多值得展开讲的地方,但为了避免过于复杂,我们点到为止,这算是“帕累托最优”(又称80/20法则)。这让我想起了 pytest,一个能即刻提高舒适度的工具。

读取文件、运行一些代码并写入另一个文件

以上,我们讨论了一些最基本的问题:输出,调试,使用外部包,以及测试。下面,我们来做一些更有效率的事情:我们可以写一个程序来处理本地文件。下面的例子将会读取 CSV 文件,计算一些数值,然后将输出结果。

为了实现该程序,我们需要在 Cargo.toml 中添加以下两行设置:

  • csv="1.1"

  • serde=version="1", features=["derive"]

你可以猜猜 main() 函数应该怎样写。

当然,这个程序还可以实现更多功能。如果你有一个非常复杂的 CSV 文件,则可以在 Rust 中调用 pandsa(pola.rs)来处理数据。我还需要进一步研究,不过似乎这种处理方法非常强大且高效。

我认为,与 Python 相比,Rust的 CSV 处理能力不相上下,除了它能自动反序列化之外。

最后,我们还可以添加一些测试,此处不再赘述。

发送 HTTP 请求

下面,我们来尝试发送基本的 HTTP 请求并处理结果。现在的绝大多数请求都需要处理 JSON。

在 Cargo.toml 中添加如下几行代码:

reqwest =  version = "0.11", features = ["json"] 
tokio =  version = "1", features = ["full"]
serde_json = "1"

这样就可以了,现在可以从 API 请求数据了。结合使用上面两个方法,我们可以获取数据,用 pola.rs 进行分析,然后将结果写入 CSV 文件中,同时保证内存安全。还记得 Python 需要循环才能实现这一点吗?在这方面 Rust 做得很好。

我相信,Rust 的生态系统会越来越大,以覆盖更多的用例,以后利用已有的 crate 实现这一切会易如反掌。

使用 SQLite

虽然在这篇文章中提到 SQLite 似乎有些奇怪,但我开发过的程序经常用到 SQLite。我很喜欢 SQLite,因为它是可移植的,非常有效,而且不需要任何维护。

用 Python 操作 SQLite 的问题永远是要不要使用 ORM。请不要误会,SQLAlchemy 非常优秀,但在进行非常小的操作时,用它就像杀鸡用牛刀了。而且 SQLAlchemy 带来的复杂性使它不适合小型嵌入式设备。

反之, Rust 可以在这方面大放异彩,网上有很多如何利用Rust操作 SQLite 的例子,我认为都非常不错。

举个简单的例子,别忘了在 Cargo.toml 中添加下面这行代码:

rusqlite =  version = "0.28.0", features = ["bundled"] 

该例子来自 rusqlite crate。当然,这只是冰山一角。但组合以上几种方法,就可以实现许多很有用的功能了。

总结

综合考虑,Rust 是一个非常优秀的语言,有许多优秀的包,非常感谢发明这门语言并为之努力贡献的开发者们。虽然这篇文章只是对 Rust 做了初步的探索,但我希望抛砖引玉,让初学者产生学习 Rust 的兴趣。

初次使用某种编程语言时,重点在于弄清楚语言本身能实现哪些功能,而不是背诵一篇完整的术语表。你不需要去理解 borrowing、继承或 traits 的具体含义,而应该跟随些入门文章按部就班地做一遍。

从无到有的难度远大于从一到十。

详细解答!从c++转向rust需要注意哪些问题?

...在日常开发过程中,若长期使用C++语言,在初次使用Rust的过程中可能会碰到一些问题。本文尝试从C++的角度来说明在使用Rust时需要特别注意的一些地方,特别是其中的思维方式的转变(mindshift)。一、赋值... 查看详情

从c++转向最受欢迎的rust语言

...在日常开发过程中,若长期使用C++语言,在初次使用Rust的过程中可能会碰到一些问题。本文尝试从C++的角度来说明在使用Rust时需要特别注意的一些地方,特别是其中的思维方式的转变(mindshift)。不久前Stac... 查看详情

1分钟插入10亿行数据!抛弃python,写脚本请使用rust

...标精彩内容不迷路  新智元报道  来源:Avinash一位程序员急需在一分钟之内生成十亿行的测试数据库,然而在用Python写了脚本之后发现「大失败」。怎么办?当然是用Rust了! 于是,他做了一个所有程序员... 查看详情

无法在 Rust/Actix 应用程序中使用带有柴油的计时功能

...】:2021-01-2001:02:23【问题描述】:我还是Rust的新手。我尝试在我的一些柴油车型中使用NaiveDateTime。因此,我尝试将chrono作为外部板条箱导入,如下所示:src/db/models.rsexterncrat 查看详情

如何将程序部署到 Solana - Solana/Rust

...a/Rust【发布时间】:2021-08-0720:33:55【问题描述】:我正在尝试运行HelloWorldsolana程序。我已经克隆了thisrepo。我已经开始了这个项目solana-test-validator我运行了npminstall,然后能够使用构建rust项目npmrunbuild:p 查看详情

8月8本程序员新书:rust软技能python量子...

8月推荐8本新书,其中有4本即将上架。1、与量子比特共舞量子计算是下一个颠覆性的技术。本书旨在带领读者探究量子计算的工作原理,并深入解释背后的数学基础。同时,本书清晰地介绍了构建量子计算机的工程... 查看详情

Rust 堆栈大小 [重复]

...icate]【发布时间】:2019-05-2718:07:21【问题描述】:我正在尝试初始化一个形状为[[u64;4096];64]的大型数组。当我尝试使用[[0;4096];64]初始化这个数组时,我会得到不同的结果,具体取决于程序的运行方式。当我使用cargotest运行时,... 查看详情

rust开发系列pyo3:rust与python的联动编程(上)

...误无法排查,无法重现,随机出现,只能靠着程序员的编码能力,在编写代码的时候小心翼翼的检查以排除,所以C/C++虽然号称也可以写出内存安全的程序,但是实际上在大型程序中,几乎是一种... 查看详情

为 ARM 交叉编译 Rust 程序时的 ALSA 链接

...forARM【发布时间】:2019-11-2400:38:33【问题描述】:我正在尝试交叉编译一个简单的Rust程序,以便在安装了libasound-dev库的Docker容器内使用wavycrate在RaspberryPiZero上使用ALSA驱动程序录制声音。但是,链接器抱怨:note:/op 查看详情

运行产生线程的可中断 Rust 程序

...hreads【发布时间】:2017-02-2222:50:11【问题描述】:我正在尝试编写一个生成一堆线程然后在最后加入线程的程序。我希望它是可中断的,因为我的计划是让它成为一个在UNIX服务中不断运行的程序。这个想法是worker_pool将包含所有... 查看详情

fridafrida的初次尝试(代码片段)

【Frida】Frida的初次尝试安装官网~$pipinstallfrida-tools~$frida-trace-i"recv*"Twitter测试直接attach一下QQ.exeimportfridadefon_message(message,data):print("[on_message]message:",message,"data:",d 查看详情

fridafrida的初次尝试(代码片段)

【Frida】Frida的初次尝试安装官网~$pipinstallfrida-tools~$frida-trace-i"recv*"Twitter测试直接attach一下QQ.exeimportfridadefon_message(message,data):print("[on_message]message:",message,"data:",d 查看详情

Rust 和 Wasm 初始设置

...在关注thistutorial使用rust创建webassembly应用程序,但是当我尝试使用node运行捆绑的web程序集代码时(在添加我自己的任何代码之前并完全按照教程进行操作)$npmrunstart>create-wasm-app@0.1.0start/Users 查看详情

matplotlib的初次使用(代码片段)

初次尝试python的matplotlib,因为论文有一堆数据要处理,只能自学。就是所谓的用到什么学什么吧。下面记录一下:首先统计所有阈值的频率,用dictionary来存储;参考官方网址对plt.bar()的各个参数解释,建立相应的柱状图。代码... 查看详情

静夜思-十年总结与展望

  回顾十年之前,2008年8月8日,那是个值得我铭记的日子,我个人初次离开长大的地方去外省求学,伴随着失意与期望,到达了另外一个地方。那天晚上,在另一个省份从电视上见证了北京奥运会的开幕。 今天2018年8... 查看详情

如何通过 wasm-pack 将 Rust Wasm 应用程序与 libpq 链接?

...-pack?【发布时间】:2020-02-2900:57:30【问题描述】:我正在尝试创建一个带有Wasm数据库层的NodeJS应用程序。我使用Rust、Diesel作为数据库驱动程序和wasm-pack作为WebAssembly编译器。当我尝试使用wasm- 查看详情

rustvspython:为啥越来越流行,取代榜一python?

参考技术A2021年,Python又获得了TIOBE年度编程语言,排名已经是第一。而Rust依然在20名以外。但依然有人认为,Rust甚至可能取代Python。不过这不重要,认清两者的优缺点,进而合适的地方使用合适的语言,这才最重要。在这个指... 查看详情

我无法在链接描述文件中指定 Rust 程序的起始偏移量是不是有原因?

...因?【发布时间】:2021-10-0214:28:36【问题描述】:我正在尝试为RaspberryPi编译一个Rust程序。我的印象是起始地址需要是0 查看详情