python的包内绝对导入,相对导入以及环境变量路径问题

学python的过程中遇到的模块导入问题造成了我很长时间的困顿,最近再重温一下模块的导入和包内模块导入,发现了一些新东西,所谓温故知新,确实如此,特来记录。

1. 模块的导入和环境变量

首先要清楚一点的是,Python的环境变量是解释器寻找文件模块的依据,环境变量第一条路径一般就是当前运行文件所在的路径,例如下面这个例子,我执行的文件是dao2.py,在test文件夹下,通过sys.path也能显示出来。

在这里插入图片描述

print(sys.path)

在这里插入图片描述

输入的环境变量列表第一条确实是当前运行文件目录\test文件夹。所以我们导包也应该尽量将包和模块放到与运行文件同一目录下,直接import导入即可,包和模块都可以通过环境变量找到。

如果是将包或模块放到了其他位置,那么通过sys.path.append()添加模块所在的目录到环境变量,也可以找到。

2. 包内模块导入

包内的导入涉及到__init__.py文件,相对导入以及绝对导入。

在文件夹中加入__init__.py文件之后,这个文件夹就变成了包,可以直接导入包来当做模块,具体知识点不再赘述,主要说说其中绝对导入和相对导入的问题。

问题1: 包内导入中经常碰到类似 ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题,发生这种问题的原因,一般是将包内的模块按照脚本模式去运行,但是在执行文件中使用了相对导入.xxx的形式,执行文件所在的目录就是环境变量的第一条路径,所以解决方法是直接使用import导入模块名或者用from xxx import绝对导入的方式,推荐用绝对导入,这时通过环境变量就可以找到要导入的模块名。举例如下:

在这里插入图片描述

# test1.py
from .test2 import hello
import sys

print(sys.path)
hello(3)

当前执行文件是test1.py,是haha包下的模块,按照脚本模式运行,不能用相对导入的形式 从test2.py中导入hello使用,test1和test2都在haha文件夹下,这里却使用了相对导入.test2的形式,那么结果就出现ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题。
在这里插入图片描述
问题2:还有一个问题就是一些博客说出现了ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这个问题可以使用绝对导入的形式解决:

# test1.py
from haha.test2 import hello
import sys

print(sys.path)
hello(3)

但是又会出现模块找不到的问题:
在这里插入图片描述
我想可能是一些博主改变了运行文件的路径才能成功,如果模块和执行文件还在一个目录下,那么加入了haha这个顶级包名,出现找不到haha的情况,问题依旧出在环境变量上。因为导入的haha这个顶级包名和环境变量中的路径重复,导致有问题,如果把包含haha这个目录的上一级目录test加到环境变量中,那么这个就不会出错了,例如下面这样:

sys.path.append(test_path)
# test1.py
from haha.test2 import hello
print(sys.path)
hello(3)

使用sys.path.append将这个test路径临时加到环境变量列表末尾。
像这样,将haha所在的文件夹test加入到环境变量里,就能够找到haha这个包了,正常输出。
在这里插入图片描述
在这里插入图片描述
或者把haha.test2改为test.haha.test2,因为环境变量包含test的上级目录,但是不包含haha的上级目录test,前面的方法是把haha的上级目录加到环境变量里面。

因此如果当前执行文件是test1.py,在haha目录下,test2.py模块也在haha目录下, 直接导入模块名即可。

# test1.py
from test2 import hello
import sys

print(sys.path)
hello(3)

用绝对导入时注意环境变量的路径问题。

在这里插入图片描述
问题3:到底什么时候使用绝对导入和相对导入,就是只能在包内进行模块的绝对导入和相对导入,如果要执行包内的模块脚本,不能用相对导入方式,应该用绝对导入或者直接导入同目录下的模块名,否则还是出现上面的问题。而且在包内使用 from aa.bb.cc.dd import ee 这种形式的导入,必须确保.的左边都是文件夹,可以是包,也可以是普通的文件目录。总之,包是当作模块来用,只需把包和要导入的模块放到和执行脚本相同的目录下正常导入就会减少出错。
总结: 其实问题的关键还是两点:
一是明确环境变量,清楚当前执行文件是在哪一个文件夹下,那么这个目录就是环境变量的第一个路径,解释器优先从这条路径找模块和代码。
二是当在包内或文件夹内运行可执行脚本文件时,注意导入模块的方式,脚本模式运行文件,文件内导入模块不能用相对导入,要用绝对导入或者直接导入同目录下的模块名,只要在环境变量的路径列表就行。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用 Python 内置的 `os` 模块来设置当前文件的路径。 举个例子: ```python import os # 设置当前文件的路径为当前工作目录 current_path = os.getcwd() print(current_path) # 设置当前文件的路径为文件所在的目录 current_path = os.path.dirname(__file__) print(current_path) ``` 其中,`os.getcwd()` 函数返回当前工作目录(即程序运行时所在的目录),`os.path.dirname(__file__)` 返回当前文件所在的目录。 注意,在使用 `__file__` 变量时,应该确保这个文件是被导入或者直接运行,否则 `__file__` 变量将是 `None`。 ### 回答2: 在Python中,我们可以通过使用`os`模块来获取当前文件的路径。 首先,我们需要导入`os`模块: ```python import os ``` 然后,使用`os`模块的`path`属性来获取当前文件的路径,可以使用`os.path.abspath(__file__)`来获得当前文件的绝对路径: ```python current_path = os.path.abspath(__file__) ``` 这个`current_path`变量将包含当前文件的绝对路径,包括文件名。 另外,如果你只想获取当前文件所在的目录路径,不包含文件名,可以使用`os.path.dirname()`方法: ```python current_directory = os.path.dirname(current_path) ``` 这个`current_directory`变量将包含当前文件所在的目录路径。 综上所述,我们可以通过这些步骤来设置Python当前文件路径变量。 ### 回答3: 在Python中,我们可以使用`__file__`变量来获取当前文件的路径。`__file__`是一个内置变量,它是一个字符串,包含了当前正在执行的脚本的文件名(或路径)。然而,需要注意的是,`__file__`返回的路径相对路径,因此需要进一步处理才能获取到绝对路径。 下面是一个示例来说明如何设置Python当前文件路径变量: ```python import os # 获取当前正在执行的脚本的文件名(或路径) current_file = __file__ # 获取当前正在执行的脚本的绝对路径 absolute_path = os.path.abspath(current_file) # 将绝对路径转换为所在目录的路径 current_directory = os.path.dirname(absolute_path) # 设置当前文件路径变量 current_file_path = current_directory print(current_file_path) ``` 在上述示例中,我们首先导入了`os`模块,然后使用`__file__`变量获取当前文件的路径,接着使用`os.path.abspath()`函数将相对路径转换为绝对路径,再使用`os.path.dirname()`函数获取所在目录的路径,最后将所在目录的路径赋值给当前文件路径变量`current_file_path`。最后,我们使用`print()`函数输出当前文件路径变量的值。 需要注意的是,以上方法只适用于在脚本文件中使用,而在交互式环境(如Python解释器的交互模式或Jupyter Notebook)中使用`__file__`变量将会引发`NameError`异常。在这种情况下,可以考虑使用`os.getcwd()`函数来获取当前工作目录的路径作为当前文件路径变量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值