Python import辨析

Python import辨析

一些概念:

  • script 脚本
  • module 模块
  • package 包
  • library 库

一、建立目录结构

Tree
|____ m1.py
|____ m2.py
|____ Branch
     |____m3.py
     |____m4.py

小例子:

# m1.py
import m2
m2.print_self()

# m2.py
def print_self():
	print("m2")

终端上运行 python m1.py

输出:m2

说明此时import是没问题的。

小例子2:

# m1.py
import m2
m2.print_self()

# m2.py
def print_self():
	print("m2")
print_self()

终端上运行 python m1.py

输出:

m2 m2

此时m2被输出了两次,这并不是我们想要的。

二、import语句的第一种用法

import module_name 即import后直接接模块名。

这种情况下,python会在两个路径下寻找模块。

  1. sys.path
  2. 当前文件所在目录

前者可通过以下语句查看内容,其实sys.path里就包含了当前文件所在目录。

import sys
print(sys.path)

小例子2的解决办法:

# m1.py
import m2
m2.print_self()

# m2.py
def print_self():
	print("this is m2")
 
print(__name__)
if __name__ == '__main__':
	print_self()

终端上运行 python m1.py

输出:

m2
this is m2

解释:在执行import时,被引入的模块的__name__会变成文件名字,在此例中为m2。因此并不会执行判断语句内的语句。

__name__为python的内置变量。可以用print(dir())查看内置变量。

小例子3:

# m1.py
import m3
m3.print_self()

# m3.py
def print_self():
	print("m3")

终端上运行 python m1.py

输出:

Traceback (most recent call last):
  File "/Users/xxx/Tree/m1.py", line 1, in <module>
    import m3
ModuleNotFoundError: No module named 'm3'

解释:此时在sys.path中找不到m3模块,这是因为m3.py和m1.py不在同一目录下。

正确做法是将import语句改为import Branch.m3。这属于绝对导入,后文会介绍。

# m1.py
import Branch.m3
Branch.m3.print_self()

三、import语句的第二种用法

from package_name import module_name 即从包中加载模块。一般把模块(module)组成的集合称为包(package)。

与第一种写法类似,Python会在sys.path运行文件目录这两个地方寻找包,然后导入包中名为module_name的模块。

例子1:

# m1.py
from Branch import m3
m3.print_self()

# m3.py
def print_self():
	print("m3")

终端上运行 python m1.py

输出:m3

说明此时from xx import xx是没问题的。

例子2:

在m4.py文件下

# m4.py
def print_self():
	print("m4")
  
# m3.py
import m4
def print_self():
	print("m3")

# m1.py
from Branch import m3
m3.print_self()

终端上运行 python m1.py

输出:

Traceback (most recent call last):
  File "/Users/xxx/Tree/m1.py", line 1, in <module>
    from Branch import m3
  File "/Users/xxx/Tree/Branch/m3.py", line 1, in <module>
    import m4
ModuleNotFoundError: No module named 'm4'

说明此时找不到m4模块,这是为什么呢?

一个解释:当前运行的是m1.py文件,sys.path和当前目录下都没有m4.py文件

四、绝对导入和相对导入

上面讲的import两种写法均属于绝对导入,即用于导入sys.path中的包和运行文件所在目录下的包。

对于sys.path中的包,这种写法毫无问题。但如果导入的是自己写的文件,如果是非运行入口文件(比如上面的m1.py是运行入口文件,可以使用绝对导入),则需要相对导入。

类似绝对路径和相对路径。例子2要想运行成功,得将m3.py改为

# m3.py
from . import m4
def print_self():
	print("m3")

相对导入的写法:

  • from . import module_name。导入和自己同目录下的模块。
  • from .package_name import module_name。导入和自己同目录的包的模块。
  • from .. import module_name。导入上级目录的模块。
  • from ..package_name import module_name。导入位于上级目录下的包的模块。

运行入口文件(m1.py)也可以使用相对导入,比如将m1.py的内容改为:

# m1.py
from .Branch import m3
m3.printSelf()

但此时不能用python m1.py命令,而是需要进入到Tree所在的目录,使用python -m Tree.m1来运行。

直接运行 ,会报错

Traceback (most recent call last):
  File "/Users/xxx/Tree/m1.py", line 1, in <module>
    from .Branch import m3
ImportError: attempted relative import with no known parent package 

一个解释:尝试在没有已知父包的情况下进行相对导入。这是因为运行m1.py时__name__变量为main,找不到父包。然而,如果m1.py的文件是被引入的,那么m1.py的__name__变量的值会包括父包路径。

五、import的其他用法

  • import moudle_name as alias

有些module_name比较长,之后写它时较为麻烦,或者module_name会出现名字冲突,可以用as来给它改名,如import numpy as np

  • from module_name import function_name, variable_name, class_name

上面导入的都是整个模块,有时候我们只想使用模块中的某些函数、某些变量、某些类,用这种写法就可以了。使用逗号可以导入模块中的多个元素。

  • 有时候导入的元素很多,可以使用反斜杠来换行,官方推荐使用括号。
from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END	# 反斜杠换行
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)	# 括号换行(推荐)

Reference:

Python中import的用法 - 门书生的文章 - 知乎 https://zhuanlan.zhihu.com/p/63143493

【python import中的绝对引用和相对引用】 https://www.bilibili.com/video/BV1EK411g7Ff?share_source=copy_web&vd_source=f263eddd9c6fc88c2b8c3f4f1f660922

python中的模块、库、包有什么区别? - 风影忍着的回答 - 知乎 https://www.zhihu.com/question/30082392/answer/2030353759

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值