每次回到Rust时,我都必须弄清楚模块系统是如何工作的。这是我将其与Python的模块系统进行比较的一些说明。
板条箱是Rust中的构建目标。板条箱可以是库,也可以是二进制文件。可以用货物建造。
在Python中,库称为“包”。二进制文件是一个完全异构的概念,通常通过配置入口点来安装。这样的二进制文件甚至不需要是Python代码(例如,它可以是Shell脚本)。
Rust中的一个软件包最多包含一个库条板箱和任意数量的二进制板条箱。 (要求至少有一个库或二进制箱。)
在Python中,一个“分发包”(即可以pip安装的包)可以包含多个“导入包”(即可以导入的包),而Rust最多允许每个分发包一个导入包。
Python将__init__.py放在包的根目录中,以指示它可以作为包导入。同样,Rust通常将lib.rs放置在板条箱的根目录中,作为库板条箱的根目录。 (与Python不同,该名称可以重新配置,但默认为lib.rs。)
在Python中,__main__.py对应于使用python -m运行时模块的主入口点。 Rust通常将main.rs作为二进制条板箱根。 (也可以重命名,如果您有多个二进制文件,则可能需要这样做。)
在Python中,所有模块都可以通过其文件系统路径名导入来使用。例如,import foo.bar首先在PYTHONPATH上查找foo /目录。然后,它在foo /目录下寻找bar /包或bar.py模块。
在Rust中,模块还对应于文件系统上的路径(默认情况下;您可以使用path属性更改此行为)。但是,仅由于存在相应的文件,它们不能立即使用!必须用mod foo声明它们;板条箱根文件中的声明(例如lib.rs)。
在Python中,嵌套模块foo.bar由foo / bar.py或foo / bar / __ init__.py实现。您不能同时使用两者。如果您想要foo.bar的子模块,则可以将其他模块或软件包放在foo / bar /下。
类似于foo.bar import qux的语句可以导入在foo / bar / __ init__.py或模块foo / bar / qux.py中声明的符号。为了清晰起见,一些开发人员选择在__init__.py中显式重新导出bar的公共接口,并在子模块前加下划线(例如_qux.py而不是qux.py)。
在Rust中,您使用foo / bar.rs声明名称空间foo :: bar的成员。如果您还希望拥有bar的子命名空间(例如foo :: bar :: qux),则可以在bar.rs旁边另外创建bar /目录。要访问bar.rs内的子命名空间qux,请在行mod qux;中输入:必须添加到bar.rs。 (这类似于我们在顶级lib.rs中添加mod foo的方式。)
要重新导出名称空间并使它对bar以外的所有用户可用,应将其更改为pub mod qux;。
主要的收获是,Rust要求在层次结构的每个步骤中使用mod显式重新导出嵌套模块,而Python则不需要。