在很长一段时间,我对于Python的导入系统以及目录操作不是很清楚,很多时候会弄错,也会觉得它很复杂。
这个问题还是在于对其中的某些概念不是很熟悉。下面会分两个部分进行说明。
Py文件的不同
在一个Python项目中,不同的py文件,他们是不同的,我觉得这个概念对于理解Python代码很重要,Java中就没有区别。这个就是Python中的入口文件和模块文件。
主要的区别是__name__
和__package__
魔术变量的值不同。当py作为入口文件时,__name__
的值为__main__,__package__
为None。而不是模块文件时,他们都是各自应该有的值。
导致这个问题的原因还是在于脚本语言,当他以文本的方式存在,而不像Java最终会形成jar包,而它所有的文件路径和管理都是在jar包内部。代码以文本的形式保存,代码用目录来组织,他们就需要解决哪里是项目的根目录的问题。
有两个目录是可以确定的:入口文件所在目录和Python程序所在的目录。这也是Python的策略。其他,编程语言也有其他策略,比如Node还可以通过配置文件来实现。
要么显示要么隐式的指定。
理解Python入口文件不能使用相对导入的方式模块也很重要。
包导入
包导入本质上来说是在解决代码复用的问题。如果,没有包导入的功能,我们所有东西都要重新写,那是非常可怕的。而包导入就是在解决这个问题。
所谓的包导入也就是系统默认从几个不同的路径来寻找模块,如果找到就其导入,没找到就报错。默认的模块路径这里就不介绍了,常见的方式就是pip安装包时,它就会安装到默认路径。
这里还有一个很重要的路径就是入口文件所在的目录,也会当做模块导入的默认路径,而且优先级最高。
注意,这是里入口文件所在的目录,而不是你执行代码的目录。这也是符合预期的,也是让我们很方便的导入入口文件所在的目录下包或者模块。
查看包导入路径的方式是
import sys
print(sys.path)
文件路径
Python中文件的读写也是很常见的方式。那么文件的路径如何指定呢?可能不同的编程语言有不同的方式。Python是通过cwd来指定,也就是当前工作目录。
当前工作目录就是执行代码的目录。可以通过如下方式获取cwd路径:
import os
print(os.getcwd())
这里有一点要注意,IDE和命令行的环境不一样,可能导致cwd的目录不同,这也会导致有些代码在IDE中可以执行,而在命令行里无法执行。不要认为Python不可理喻,只是我们缺少一些信息。
__init__.py
__init__.py
文件可以理解为就是在为__all__服务,告诉他人当前package中哪些是可以对外使用的。
我们可以理解为import xx导入都是模块。导入包也是导入模块。如果想导入模块中的特定方法、变量就需要使用 from xxx import xx
的形式。