1) "import X" 与 "from X import Y"
我们有两个文件------main.py
是我们运行的文件,helper.py
是我们从中导入的文件。
这里有两种主要的导入方式:
和
这两种方式都是有效的,各有优缺点:
在 "from helper import testfunc"
中,我们只需输入 testfunc()
即可使用它,而在 "import helper"
中,我们需要输入 helper.testfunc()
.
然而,在更大、更复杂的应用程序中,"from helper import testfunc"
有更高的可能性会导致命名空间冲突------即意外覆盖同名的其他函数/变量.
相反,"import helper"
不会意外覆盖名为 testfunc
的其他函数/变量,因为它有命名空间(helper.testfunc
).
2) "from X import Y" 与 "from X import *"
from helper import testfunc
只导入 testfunc
函数.
from helper import *
导入 helper.py
中的一切.
虽然 from helper import *
一开始看起来更方便,但实际上被认为是不好的做法.
当我们使用 from helper import *
时,我们从 helper.py
中导入了一切,这也意味着一些导入的函数/变量可能会意外覆盖同名的现有函数/变量.
因此,通常更好的做法是明确声明我们正在导入的内容,而不是导入文件中的所有内容.
3) 使用 __import__
进行动态导入
这允许我们使用字符串动态导入模块.
4) sys.path
和导入的位置
当我们导入东西时,Python 有一个要搜索的文件夹列表.
我们可以通过打印 sys.path
来查看这个文件夹列表.
当我们导入某物,例如 pandas 时,Python 会尝试在第一个文件夹 /Users/me/Documents/test
中找到 pandas.
如果它存在于这个第一个文件夹中,Python 就会从这里导入 pandas.否则,Python 将继续下一个文件夹 /some/other/path
并尝试从那里导入 pandas.
这个过程会一直重复,直到没有更多的文件夹供 Python 搜索为止.当这种情况发生时,我们会得到一个 ImportError
.
5) 我们可以手动添加内容到 sys.path
sys.path
是一个普通的字符串列表. Python 只是恰好从 sys.path
中的路径搜索模块.
假设我们需要从 /some/weird/path/test.py
导入一些函数.
而我们正在使用 /our/main/path/main.py
------一个完全不同的路径.
因此,我们可以简单地将 /some/weird/path
添加到 sys.path
中,以便 Python 知道我们希望从 /some/weird/path
这个位置搜索.
在将 some/weird/path
添加到 sys.path
之后,我们现在可以从该目录中导入而不会出现问题.
6) PEP8 的导入顺序
我曾在工作中被我的技术主管责备过没有遵循这个规则.
PEP8(Python 增强提案 8)是一份陈述 Python 代码风格最佳实践的文档.
关于导入,我们最好按照以下方式排序:
- 标准库导入,例如
os, sys, json, re
- 相关的第三方导入,例如
pandas, numpy, fastapi
- 本地库特定导入,例如
our_custom_modules
记得在每个组之间添加一个换行符以提高可读性.
注意------Python 不会强制执行这一点(但你的技术主管可能会)
7) __all__
和从文件中"导出"
特殊的 __all__
变量控制从文件中导入的内容.
我们有两个文件------main.py
是我们运行的文件,helper.py
是 main.py
从中导入的文件.
helper.py
包含一堆函数,但它有一个 __all__
变量.
在这里,__all__
变量使得只有 hello
和 hi
在我们执行 from helper import *
时被导出.
在这里,由于只有 hello
和 hi
从 hello.py
中导出,main.py
只导入了 hello
和 hi
.
这意味着 hola
和 nihao
没有被导入.
因此,__all__
变量可以用来限制 Python 模块中导出的内容,如果我们的模块杂乱且包含许多变量,这尤其有用.
8) 以 _
开头的变量在 "from X import *" 时不被导入
我们有两个文件------main.py
是我们运行的文件,helper.py
是 main.py
从中导入的文件.
在 helper.py
中,我们有两个普通函数和两个以 _
开头的函数名.
当我们执行 "from helper import *"
时,以 _
开头的变量/函数不会被导入.
9) PYTHONPATH
环境变量
PYTHONPATH
是我们选择定义的一个环境变量.如果我们定义了它,PYTHONPATH
就会自动添加到 sys.path
中.
在以下示例中,我们没有定义 PYTHONPATH
:
在下一个示例中,我们将 PYTHONPATH
设置为 /some/funny/path
因此,/some/funny/path
会自动添加到 sys.path
中,我们可以观察到这一点.现在,当我们导入 Python 中的东西时,Python 会自动搜索我们的 PYTHONPATH
.
如果我们希望从其他路径导入模块,但不希望将当前目录与该位置耦合## 10) 在导入过程中使用 __name__
__name__
是 Python 中的另一个特殊变量.
当我们直接运行一个文件时,__name__
默认为字符串值 '__main__'
.
相反,在导入的文件中,__name__
不是 '__main__'
,而是 Python 文件的名称.
在这里,我们直接运行 a.py
.因此,a.py
中的 __name__
默认为 '__main__'
.
b.py
和 c.py
没有被直接运行.相反,我们从它们中导入.因此,b.py
中的 __name__
是 b
,而 c.py
中的 __name__
是 c
.
这就是为什么我们经常在 Python 代码中看到 if __name__ == "__main__"
------这是为了确保只有当我们直接运行这个特定的 Python 文件时,这个块内的内容才会运行.