Python:import语句的详细解析(绝对路径导入和相对路径导入)

news2025/1/10 2:01:09

相关阅读

Pythonicon-default.png?t=O83Ahttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm=1001.2014.3001.5482


        import语句是Python中一个很重要的机制,允许在一个文件中访问另一个文件的函数、类、变量等,本文就将进行详细介绍。

        在具体谈论import语句前,首先介绍相关的前置知识——导入的搜索目录。

导入的搜索目录

        既然要求在一个文件访问其他文件,那么如何找到其他文件就是一个问题,这由sys包中的path列表决定,它在Python解释器在启动时会自动初始化,并属于整个Python解释器而不是某个文件。

        初始化后的sys.path列表由多个元素组成,每个元素都是一个字符串,表示在导入时会依次搜索的路径(除内建模块外,比如math)。

        sys.path列表第一个元素会根据Python解释器的启动方式而定:

        1、如果是以交互式启动,则会被设置为空字符串,以表示当前工作目录,如例1所示(空字符串永远代表当前工作目录,即使在交互式Python中使用os.chdir函数改变了当前工作目录)。

# 例1
# 命令行
(test) C:\Users\12078\Desktop>python
Python 3.10.14 | packaged by Anaconda, Inc. | (main, May  6 2024, 19:44:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'D:\\Anaconda\\envs\\test\\python310.zip', 'D:\\Anaconda\\envs\\test\\DLLs', 'D:\\Anaconda\\envs\\test\\lib', 'D:\\Anaconda\\envs\\test', 'D:\\Anaconda\\envs\\test\\lib\\site-packages']

        2、如果以python  -m命令启动,则会被设置当前工作目录,如例2所示(注意其与例1的区别)。

# 例2
# 文件test1.py
import sys
print(sys.path)

# 命令行
(test) C:\Users\12078\Desktop>python -m example.test1
['C:\\Users\\12078\\Desktop', 'D:\\Anaconda\\envs\\test\\python310.zip', 'D:\\Anaconda\\envs\\test\\DLLs', 'D:\\Anaconda\\envs\\test\\lib', 'D:\\Anaconda\\envs\\test', 'D:\\Anaconda\\envs\\test\\lib\\site-packages']

        3、如果是以普通的python命令启动(最常见),则会被设置为命令行中脚本文件所在的目录,如例3所示(本文将这种情况为例)。

# 例3
# 文件test1.py
import sys
print(sys.path)

# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
['C:\\Users\\12078\\Desktop\\example', 'D:\\Anaconda\\envs\\test\\python310.zip', 'D:\\Anaconda\\envs\\test\\DLLs', 'D:\\Anaconda\\envs\\test\\lib', 'D:\\Anaconda\\envs\\test', 'D:\\Anaconda\\envs\\test\\lib\\site-packages']

        sys.path列表中的其他元素还包括环境变量PYTHONPATH中指定的目录、标准库路径、site-packages目录等。该列表可以在程序执行时被添加、删除元素,就像一个普通的列表那样,但是这是需要谨慎,因为可能出现导入相关的问题。

import语句的语法

        下面是Python官方文档中,对于import语句的描述,由于imort语句分为基本import语句和from import语句,下面将分别讨论。

import_stmt     ::=  "import" module ["as" identifier] ("," module ["as" identifier])*
                     | "from" relative_module "import" identifier ["as" identifier]
                     ("," identifier ["as" identifier])*
                     | "from" relative_module "import" "(" identifier ["as" identifier]
                     ("," identifier ["as" identifier])* [","] ")"
                     | "from" relative_module "import" "*"
module          ::=  (identifier ".")* identifier
relative_module ::=  "."* module | "."+

基本import语句

        基本import语句的执行分两步进行,首先会在导入的搜索目录中,根据模块的import路径查找并导入(如果已导入,则不会重复导入),随后在import语句执行位置所在的命名空间定义若干标识符(代表了模块类的实例)。

import路径

        一个以.py后缀的文件或包(即目录)可以代表一个模块,对于import路径,路径分隔符不再是斜杠(对于Linux系统)或反斜杠(对于Windows系统)而是点,且对于.py后缀的文件不添加.py后缀。由于是在导入的搜索目录中对import路径进行查找,所以同一个文件,如果在不同的搜索路径下导入,使用的import路径是不同的。

        图1展示了例3的文件结构,例4给出了几个import路径的示例,假设执行的是test1.py文件(因此'C:\\Users\\12078\\Desktop\\example'是sys.path列表的第一个元素)。

图1 文件结构 

# 例4
Package                        # 这是一个包的import路径
Package.__init__               # 这是一个.py文件的import路径
Package.test2                  # 这是一个.py文件的import路径
example.Package                # 这是不合法的, 要相对sys.path中的路径
example.Package.test2          # 这是不合法的, 要相对sys.path中的路径
Package.test2.func1            # 这是不合法的, 一个函数不是模块
模块导入

        导入一个模块,会执行模块内的所有代码(包也是一种模块,对于这种模块来说是指执行了包中的__init__.py文件),并在sys.modules字典(它和sys.path一样属于整个Python解释器)中以添加模块的import路径为键,模块对象为值,如例5所示,假设执行的是test1.py文件。Python解释器根据import路径避免重复导入,注意这不是绝对路径,所以可能两个同名文件的import路径相同导致第二个导入无法进行,也可能同一个文件因为其具有不同的import路径被重复导入。

# 例5
# 文件test1.py
import sys
print(sys.modules)
import Package.test2
print(sys.modules)
import Package


# 文件__init__.py
def fun():
    print("func in __init__.py")
print("This is a package's __init__.py")


# 文件test2.py
def fun1c():
    print("func1 in test2.py")
def fun2c():
    print("func2 in test2.py")

print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module '_io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from 'D:\\Anaconda\\envs\\test\\lib\\codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\aliases.py'>, 'encodings': <module 'encodings' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\utf_8.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\gbk.py'>, '_signal': <module '_signal' (built-in)>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from 'D:\\Anaconda\\envs\\test\\lib\\abc.py'>, 'io': <module 'io' from 'D:\\Anaconda\\envs\\test\\lib\\io.py'>, '__main__': <module '__main__' from 'C:\\Users\\12078\\Desktop\\example\\test1.py'>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from 'D:\\Anaconda\\envs\\test\\lib\\stat.py'>, '_collections_abc': <module '_collections_abc' from 'D:\\Anaconda\\envs\\test\\lib\\_collections_abc.py'>, 'genericpath': <module 'genericpath' from 'D:\\Anaconda\\envs\\test\\lib\\genericpath.py'>, '_winapi': <module '_winapi' (built-in)>, 'ntpath': <module 'ntpath' from 'D:\\Anaconda\\envs\\test\\lib\\ntpath.py'>, 'os.path': <module 'ntpath' from 'D:\\Anaconda\\envs\\test\\lib\\ntpath.py'>, 'os': <module 'os' from 'D:\\Anaconda\\envs\\test\\lib\\os.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'D:\\Anaconda\\envs\\test\\lib\\_sitebuiltins.py'>, '_distutils_hack': <module '_distutils_hack' from 'D:\\Anaconda\\envs\\test\\lib\\site-packages\\_distutils_hack\\__init__.py'>, 'site': <module 'site' from 'D:\\Anaconda\\envs\\test\\lib\\site.py'>}
This is a package's __init__.py
This is test2.py
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module '_io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from 'D:\\Anaconda\\envs\\test\\lib\\codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\aliases.py'>, 'encodings': <module 'encodings' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\utf_8.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'D:\\Anaconda\\envs\\test\\lib\\encodings\\gbk.py'>, '_signal': <module '_signal' (built-in)>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from 'D:\\Anaconda\\envs\\test\\lib\\abc.py'>, 'io': <module 'io' from 'D:\\Anaconda\\envs\\test\\lib\\io.py'>, '__main__': <module '__main__' from 'C:\\Users\\12078\\Desktop\\example\\test1.py'>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from 'D:\\Anaconda\\envs\\test\\lib\\stat.py'>, '_collections_abc': <module '_collections_abc' from 'D:\\Anaconda\\envs\\test\\lib\\_collections_abc.py'>, 'genericpath': <module 'genericpath' from 'D:\\Anaconda\\envs\\test\\lib\\genericpath.py'>, '_winapi': <module '_winapi' (built-in)>, 'ntpath': <module 'ntpath' from 'D:\\Anaconda\\envs\\test\\lib\\ntpath.py'>, 'os.path': <module 'ntpath' from 'D:\\Anaconda\\envs\\test\\lib\\ntpath.py'>, 'os': <module 'os' from 'D:\\Anaconda\\envs\\test\\lib\\os.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'D:\\Anaconda\\envs\\test\\lib\\_sitebuiltins.py'>, '_distutils_hack': <module '_distutils_hack' from 'D:\\Anaconda\\envs\\test\\lib\\site-packages\\_distutils_hack\\__init__.py'>, 'site': <module 'site' from 'D:\\Anaconda\\envs\\test\\lib\\site.py'>, 'Package': <module 'Package' from 'C:\\Users\\12078\\Desktop\\example\\Package\\__init__.py'>, 'Package.test2': <module 'Package.test2' from 'C:\\Users\\12078\\Desktop\\example\\Package\\test2.py'>}

        可以看出,在test2.py文件(导入)执行前,Package包中的__init__.py文件先(导入)执行了,因为所有import路径上的目录(包)会从浅到深依次导入,最后导入目标模块,从导入后的sys.modules字典中也可以看到Package包比Package.test2模块添加得更早。如果在此之后,再次导入Package,__init__.py文件不会再(导入)执行了,因为Python解释器会避免重复导入。

定义标识符

        在import语句执行后,会在当前命名空间定义标识符,引用了被导入的模块,用于访问导入的模块(对于导入的包,指的是其__init__.py文件)中全局命名空间下的函数、类、变量等,需要注意的是导入是针对整个Python解释器而言的,而定义标识符是针对在当前命名空间而言的,两个步骤并不一定会全部完成(如例8的as子句和之后的from import语句所示)。Python解释器中所有导入的模块都会在sys.modules字典中创建键值对,使用它可以访问所有导入的模块(谨慎使用,因为这允许一个文件可以访问另一个文件中导入的模块)。

        例6中展示了在当前命名空间定义标识符的过程。

# 例6
# 文件test1.py
import math
import Package.test2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符Package和Package.test2
Package.func()         # 可以用标识符调用__init__.py中的函数
Package.test2.func1()  # 可以用标识符调用test2.py中的函数
import sys
sys.modules["Package"].func() # 可以用sys.modules字典来调用__init__.py中的函数
sys.modules["Package.test2"].func1() # 也可以用sys.modules字典来调用test2.py中的函数

def ttt():
   Package.func() # 局部命名空间可以访问全局命名空间的标识符

ttt() # 调用ttt函数


# 文件__init__.py
def func():
    print("func in __init__.py")
print("This is a package's __init__.py")

# 文件test2.py
import sys
print(sys.modules["math"].sqrt(4))  # 使用sys可以让一个文件访问不是在该文件中导入的模块
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")

print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
This is a package's __init__.py
2
This is test2.py
func in __init__.py
func1 in test2.py
func in __init__.py
func1 in test2.py
func in __init__.py

控制导入模块的执行

        如果希望某些代码在模块导入时不执行,则可以如例7所示,这利用了只有直接执行而非导入执行时,__name__变量才为"__main__"的性质。

# 例7
# 文件test1.py
import Package.test2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符Package和Package.test2
Package.func()         # 可以调用__init__.py中的函数了
Package.test2.func1()  # 可以调用test2.py中的函数了

def ttt():
   Package.func() # 局部命名空间可以访问全局命名空间的标识符

ttt() # 调用ttt函数


# 文件__init__.py
def func():
    print("func in __init__.py")

if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")

if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
func in __init__.py
fun1c in test2.py
func in __init__.py

as子句

        如果模块的路径很长,则定义的标识符也会很长,此时使用as子句就可以用指定的标识符代表该模块,如例8所示,需要小心这可能会导致标识符的覆盖问题。

# 例8
# 文件test1.py
import sys
import Package.test2 as t2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符t2
# Package.func()   不可以调用__init__.py中的函数, 因为虽然Package包被导入, 但此时没有定义该标识符
sys.modules["Package"].func() # 此时只能用sys.modules字典来调用__init__.py中的函数
# Package.test2.func1() 不可以调用test2.py中的函数,因为虽然Package.test2模块被导入, 但此时没有定义该标识符
t2.func1()  # 可以用新的标识符调用test2.py中的函数
sys.modules["Package.test2"].func1() # 也可以用sys.modules字典来调用test2.py中的函数

import Package.test2 # 由于Package包和Package.test2模块已被导入, 这导致直接在全局命名空间定义标识符Package和Package.test2
Package.func() # 用标识符来调用__init__.py中的函数
Package.test2.func1() # 用标识符来调用test2.py中的函数


# 文件__init__.py
def func():
    print("func in __init__.py")

if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")

if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
func in __init__.py
func1 in test2.py
func1 in test2.py
func in __init__.py
func1 in test2.py
多重import语句 

        多个import语句可以合并为同一个语句,当语句包含多个子句(由逗号分隔)时这两个步骤将对每个子句分别执行,如同这些子句被分成独立的import语句一样,例9重写了例8。

# 例9
# 文件test1.py
import Package.test2 as t2, Package.test2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 接着在全局命名空间定义标识符t2, 最后在全局命名空间定义标识符Package和Package.test2
t2.func1()  # 用新的标识符调用test2.py中的函数
Package.func()
Package.test2.func1()


# 文件__init__.py
def func():
    print("func in __init__.py")

if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")

if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop>python .\example\test1.py
fun1c in test2.py
func in __init__.py
fun1c in test2.py

删除导入的模块

        如果想完全删除导入的模块,其实也就是删除只想其的所有引用,每个被导入的模块有两处引用,来自import语句引入的标识符和sys.modules字典中的键值对,所以可以直接使用del语句删除import语句引入的标识符,然后del语句删除sys.modules字典中的值(这之后允许再次导入,因为解释器是根据sys.modules中的import路径决定是否能重新导入),只有删除了这两个引用,才能完全删除导入的模块,如例10所示。

# 例10
# 命令行
(test) C:\Users\12078\Desktop>python
>>> import Package
This is a package's __init__.py
>>> import sys
>>> sys.getrefcount(Package)     # getrefcount函数可以得到一个对象的引用个数
3                                # 三处引用分别来自于Packge标识符、sys.modules字典和getrefcount函数执行时临时添加的
>>> del sys.modules["Package"]
>>> sys.getrefcount(Package)
2
>>> del Package 

from import语句

        首先按照简单的情况分析,即from后跟着的路径可以像之前一样是一个普通的import路径(为区别,称为绝对路径)。在文末会对相对路径导入进行讨论,这是from import语句特有的。

import路径

        与基本import语句一样,一个以.py后缀的文件或包(即目录)可以代表一个模块,对于import路径,路径分隔符不再是斜杠(对于Linux系统)或反斜杠(对于Windows系统)而是点,且对于.py后缀的文件不添加.py后缀。

模块导入

        根据import路径的不同,from import语句会有不同的效果,如import路径代表了一个包,则import后的必须是一个包(目录)内(注意不是__init__.py文件中)的模块;如import路径代表了一个.py文件,则import后的必须是该文件内的全局命名空间下的函数、类、变量等。

        与基本import语句相同,所有import路径上的目录(包)会从浅到深依次导入(执行),对于import路径代表了一个包,包内的模块是最后导入(执行)的。所有导入的模块都会在sys.modules字典(它和sys.path一样属于整个Python解释器)中以添加模块的import路径为键,模块对象为值。

定义标识符

        如果import后的是一个包内的模块,会在当前命名空间定义标识符,引用了import后被导入的模块(注意,虽然所有import路径上的目录(包)会从浅到深依次导入,但不会定义标识符),用于访问导入的模块(对于导入的包,指的是其__init__.py文件)中全局命名空间下的函数、类、变量等;如果import路径代表了一个.py文件,则import后的函数、类、变量标识符会被引入,如例11所示。如果import后是*,代表包内的所有模块或py文件内全局命名空间的所有标识符

# 例11
# 文件test1.py
from Package import test2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符test2
# 上面的导入的效果就像是 import Package.test2 as test2, 导入(执行)了Package包但没有定义Package标识符
# Package.func()   不可以调用__init__.py中的函数, 因为虽然Package包被导入, 但此时没有定义该标识符
import sys
sys.modules["Package"].func() # 此时只能用sys.modules字典来调用__init__.py中的函数
from Package.test2 import func1 # 在全局命名空间定义标识符func1
from Package.test2 import func2 # 在全局命名空间定义标识符func2
func1()
func2()


# 文件__init__.py
def func():
    print("func in __init__.py")
if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")
if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop\example>python test1.py
​func in __init__.py
func1 in test2.py
func2 in test2.py

as子句

        这部分的与基本import语句相同。

多重from import语句

        多个from import语句可以合并为同一个语句,当语句包含多个子句(由逗号分隔,如果用可选的小括号包围时结尾可以有多余的逗号)时如同这些子句被分成独立的import语句一样,例12重写了例11。

​# 例12
# 文件test1.py
from Package.test2 import func1, func2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符func1和func2
# from Package.test2 import (func1, func2) 等价表示
# from Package.test2 import (func1, func2,) 等价表示
func1()
func2()


# 文件__init__.py
def func():
    print("func in __init__.py")
if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")
if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop\example>python test1.py
​func in __init__.py
func1 in test2.py
func2 in test2.py

删除导入的模块

        这部分的与基本import语句相同。

相对路径导入

        相对导入是一个难点,本节将详细解释。

        首先忘掉sys.path列表,相对路径导入并不是在导入的搜索目录中进行搜索。我们将前面带有若干点.的路径和只由若干点组成的路径称为相对路径。

        当一个模块还未完全被导入(执行)时,其实就能在sys.modules中看到它了,如例13所示。

​# 例13
# 文件test1.py
from Package.test2 import func1, func2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符func1和func2


# 文件__init__.py
def func():
    print("func in __init__.py")
if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
import sys
print(sys.modules)
def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")
if __name__ == "__main__":
    print("This is test2.py")


# 命令行
(test) C:\Users\12078\Desktop\example>python test1.py

        这和相对路径导入有什么关系呢?其实相对导入是通过sys.modules中本模块的import路径反查绝对路径来查找的。有一点需要注意,绝对路径的层级不能高于本模块的import路径的第一级。这也许听起来令人费解,例14展示了一个具体的例子。

​# 例14
# 文件test1.py
from Package.test2 import func1, func2 # 首先导入(执行)Package包, 随后导入(执行)Package.test2模块, 最后在全局命名空间定义标识符func1和func2


# 文件__init__.py
def func():
    print("func in __init__.py")
if __name__ == "__main__":
    print("This is a package's __init__.py")


# 文件test2.py
import sys
print(sys.modules)
print(sys.path)
del sys.path[0]
print(sys.path)
from .test3 import *
from . import test3
# from ..Package.test3 import * 报错:ImportError: attempted relative import beyond top-level package
# from .. import Package 报错:ImportError: attempted relative import beyond top-level package

print(sys.modules)

def func1():
    print("func1 in test2.py")
def func2():
    print("func2 in test2.py")
if __name__ == "__main__":
    print("This is test2.py")


# 文件test3.py(与test2.py一起在Package中)
def func3():
    print("func3 in test3.py")


# 命令行
(test) C:\Users\12078\Desktop\example>python test1.py
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, '_frozen_importlib_external': <module 'importlib._bootstrap_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from 'D:\\Anaconda\\lib\\codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from 'D:\\Anaconda\\lib\\encodings\\aliases.py'>, 'encodings': <module 'encodings' from 'D:\\Anaconda\\lib\\encodings\\__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'D:\\Anaconda\\lib\\encodings\\utf_8.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'D:\\Anaconda\\lib\\encodings\\gbk.py'>, '_signal': <module '_signal' (built-in)>, 'encodings.latin_1': <module 'encodings.latin_1' from 'D:\\Anaconda\\lib\\encodings\\latin_1.py'>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from 'D:\\Anaconda\\lib\\abc.py'>, 'io': <module 'io' from 'D:\\Anaconda\\lib\\io.py'>, '__main__': <module '__main__' from 'C:\\Users\\12078\\Desktop\\example\\test1.py'>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from 'D:\\Anaconda\\lib\\stat.py'>, '_collections_abc': <module '_collections_abc' from 'D:\\Anaconda\\lib\\_collections_abc.py'>, 'genericpath': <module 'genericpath' from 'D:\\Anaconda\\lib\\genericpath.py'>, 'ntpath': <module 'ntpath' from 'D:\\Anaconda\\lib\\ntpath.py'>, 'os.path': <module 'ntpath' from 'D:\\Anaconda\\lib\\ntpath.py'>, 'os': <module 'os' from 'D:\\Anaconda\\lib\\os.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'D:\\Anaconda\\lib\\_sitebuiltins.py'>, '_locale': <module '_locale' (built-in)>, '_bootlocale': <module '_bootlocale' from 'D:\\Anaconda\\lib\\_bootlocale.py'>, '_distutils_hack': <module '_distutils_hack' from 'D:\\Anaconda\\lib\\site-packages\\_distutils_hack\\__init__.py'>, 'types': <module 'types' from 'D:\\Anaconda\\lib\\types.py'>, 'importlib._bootstrap': <module 'importlib._bootstrap' (frozen)>, 'importlib._bootstrap_external': <module 'importlib._bootstrap_external' (frozen)>, 'warnings': <module 'warnings' from 'D:\\Anaconda\\lib\\warnings.py'>, 'importlib': <module 'importlib' from 'D:\\Anaconda\\lib\\importlib\\__init__.py'>, 'importlib.machinery': <module 'importlib.machinery' from 'D:\\Anaconda\\lib\\importlib\\machinery.py'>, '_heapq': <module '_heapq' (built-in)>, 'heapq': <module 'heapq' from 'D:\\Anaconda\\lib\\heapq.py'>, 'itertools': <module 'itertools' (built-in)>, 'keyword': <module 'keyword' from 'D:\\Anaconda\\lib\\keyword.py'>, '_operator': <module '_operator' (built-in)>, 'operator': <module 'operator' from 'D:\\Anaconda\\lib\\operator.py'>, 'reprlib': <module 'reprlib' from 'D:\\Anaconda\\lib\\reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'collections': <module 'collections' from 'D:\\Anaconda\\lib\\collections\\__init__.py'>, 'collections.abc': <module 'collections.abc' from 'D:\\Anaconda\\lib\\collections\\abc.py'>, '_functools': <module '_functools' (built-in)>, 'functools': <module 'functools' from 'D:\\Anaconda\\lib\\functools.py'>, 'contextlib': <module 'contextlib' from 'D:\\Anaconda\\lib\\contextlib.py'>, 'enum': <module 'enum' from 'D:\\Anaconda\\lib\\enum.py'>, '_sre': <module '_sre' (built-in)>, 'sre_constants': <module 'sre_constants' from 'D:\\Anaconda\\lib\\sre_constants.py'>, 'sre_parse': <module 'sre_parse' from 'D:\\Anaconda\\lib\\sre_parse.py'>, 'sre_compile': <module 'sre_compile' from 'D:\\Anaconda\\lib\\sre_compile.py'>, 'copyreg': <module 'copyreg' from 'D:\\Anaconda\\lib\\copyreg.py'>, 're': <module 're' from 'D:\\Anaconda\\lib\\re.py'>, 'typing.io': <class 'typing.io'>, 'typing.re': <class 'typing.re'>, 'typing': <module 'typing' from 'D:\\Anaconda\\lib\\typing.py'>, 'importlib.abc': <module 'importlib.abc' from 'D:\\Anaconda\\lib\\importlib\\abc.py'>, 'importlib.util': <module 'importlib.util' from 'D:\\Anaconda\\lib\\importlib\\util.py'>, 'mpl_toolkits': <module 'mpl_toolkits' (namespace)>, 'sphinxcontrib': <module 'sphinxcontrib' (namespace)>, 'zope': <module 'zope' from 'D:\\Anaconda\\lib\\site-packages\\zope\\__init__.py'>, 'site': <module 'site' from 'D:\\Anaconda\\lib\\site.py'>, 'Package': <module 'Package' from 'C:\\Users\\12078\\Desktop\\example\\Package\\__init__.py'>, 'Package.test2': <module 'Package.test2' from 'C:\\Users\\12078\\Desktop\\example\\Package\\test2.py'>}
['C:\\Users\\12078\\Desktop\\example', 'D:\\Anaconda\\python39.zip', 'D:\\Anaconda\\DLLs', 'D:\\Anaconda\\lib', 'D:\\Anaconda', 'D:\\Anaconda\\lib\\site-packages', 'D:\\Anaconda\\lib\\site-packages\\win32', 'D:\\Anaconda\\lib\\site-packages\\win32\\lib', 'D:\\Anaconda\\lib\\site-packages\\Pythonwin']
['D:\\Anaconda\\python39.zip', 'D:\\Anaconda\\DLLs', 'D:\\Anaconda\\lib', 'D:\\Anaconda', 'D:\\Anaconda\\lib\\site-packages', 'D:\\Anaconda\\lib\\site-packages\\win32', 'D:\\Anaconda\\lib\\site-packages\\win32\\lib', 'D:\\Anaconda\\lib\\site-packages\\Pythonwin']
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, '_frozen_importlib_external': <module 'importlib._bootstrap_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from 'D:\\Anaconda\\lib\\codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from 'D:\\Anaconda\\lib\\encodings\\aliases.py'>, 'encodings': <module 'encodings' from 'D:\\Anaconda\\lib\\encodings\\__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'D:\\Anaconda\\lib\\encodings\\utf_8.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'D:\\Anaconda\\lib\\encodings\\gbk.py'>, '_signal': <module '_signal' (built-in)>, 'encodings.latin_1': <module 'encodings.latin_1' from 'D:\\Anaconda\\lib\\encodings\\latin_1.py'>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from 'D:\\Anaconda\\lib\\abc.py'>, 'io': <module 'io' from 'D:\\Anaconda\\lib\\io.py'>, '__main__': <module '__main__' from 'C:\\Users\\12078\\Desktop\\example\\test1.py'>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from 'D:\\Anaconda\\lib\\stat.py'>, '_collections_abc': <module '_collections_abc' from 'D:\\Anaconda\\lib\\_collections_abc.py'>, 'genericpath': <module 'genericpath' from 'D:\\Anaconda\\lib\\genericpath.py'>, 'ntpath': <module 'ntpath' from 'D:\\Anaconda\\lib\\ntpath.py'>, 'os.path': <module 'ntpath' from 'D:\\Anaconda\\lib\\ntpath.py'>, 'os': <module 'os' from 'D:\\Anaconda\\lib\\os.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'D:\\Anaconda\\lib\\_sitebuiltins.py'>, '_locale': <module '_locale' (built-in)>, '_bootlocale': <module '_bootlocale' from 'D:\\Anaconda\\lib\\_bootlocale.py'>, '_distutils_hack': <module '_distutils_hack' from 'D:\\Anaconda\\lib\\site-packages\\_distutils_hack\\__init__.py'>, 'types': <module 'types' from 'D:\\Anaconda\\lib\\types.py'>, 'importlib._bootstrap': <module 'importlib._bootstrap' (frozen)>, 'importlib._bootstrap_external': <module 'importlib._bootstrap_external' (frozen)>, 'warnings': <module 'warnings' from 'D:\\Anaconda\\lib\\warnings.py'>, 'importlib': <module 'importlib' from 'D:\\Anaconda\\lib\\importlib\\__init__.py'>, 'importlib.machinery': <module 'importlib.machinery' from 'D:\\Anaconda\\lib\\importlib\\machinery.py'>, '_heapq': <module '_heapq' (built-in)>, 'heapq': <module 'heapq' from 'D:\\Anaconda\\lib\\heapq.py'>, 'itertools': <module 'itertools' (built-in)>, 'keyword': <module 'keyword' from 'D:\\Anaconda\\lib\\keyword.py'>, '_operator': <module '_operator' (built-in)>, 'operator': <module 'operator' from 'D:\\Anaconda\\lib\\operator.py'>, 'reprlib': <module 'reprlib' from 'D:\\Anaconda\\lib\\reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'collections': <module 'collections' from 'D:\\Anaconda\\lib\\collections\\__init__.py'>, 'collections.abc': <module 'collections.abc' from 'D:\\Anaconda\\lib\\collections\\abc.py'>, '_functools': <module '_functools' (built-in)>, 'functools': <module 'functools' from 'D:\\Anaconda\\lib\\functools.py'>, 'contextlib': <module 'contextlib' from 'D:\\Anaconda\\lib\\contextlib.py'>, 'enum': <module 'enum' from 'D:\\Anaconda\\lib\\enum.py'>, '_sre': <module '_sre' (built-in)>, 'sre_constants': <module 'sre_constants' from 'D:\\Anaconda\\lib\\sre_constants.py'>, 'sre_parse': <module 'sre_parse' from 'D:\\Anaconda\\lib\\sre_parse.py'>, 'sre_compile': <module 'sre_compile' from 'D:\\Anaconda\\lib\\sre_compile.py'>, 'copyreg': <module 'copyreg' from 'D:\\Anaconda\\lib\\copyreg.py'>, 're': <module 're' from 'D:\\Anaconda\\lib\\re.py'>, 'typing.io': <class 'typing.io'>, 'typing.re': <class 'typing.re'>, 'typing': <module 'typing' from 'D:\\Anaconda\\lib\\typing.py'>, 'importlib.abc': <module 'importlib.abc' from 'D:\\Anaconda\\lib\\importlib\\abc.py'>, 'importlib.util': <module 'importlib.util' from 'D:\\Anaconda\\lib\\importlib\\util.py'>, 'mpl_toolkits': <module 'mpl_toolkits' (namespace)>, 'sphinxcontrib': <module 'sphinxcontrib' (namespace)>, 'zope': <module 'zope' from 'D:\\Anaconda\\lib\\site-packages\\zope\\__init__.py'>, 'site': <module 'site' from 'D:\\Anaconda\\lib\\site.py'>, 'Package': <module 'Package' from 'C:\\Users\\12078\\Desktop\\example\\Package\\__init__.py'>, 'Package.test2': <module 'Package.test2' from 'C:\\Users\\12078\\Desktop\\example\\Package\\test2.py'>, 'Package.test3': <module 'Package.test3' from 'C:\\Users\\12078\\Desktop\\example\\Package\\test3.py'>}

        import路径前的一个点表示当前模块的包(该例中指Package目录)内,而两个点表示所处的包的父包(该例中指example目录)内,以此类推,只使用一个点表示表示当前模块的包,而两个点表示当前模块所处的包的父包,以此类推。

        文件一中使用from import语句和绝对路径导入了test2.py文件,在test2.py文件中,首先将sys.path中的第一个元素删除(这是为了确保相对导入与sys.path无关),随后使用了相对路径导入,其中前两种是正确的,而后两种是错误的,因为它们使用两个点访问了..(该例中指example目录),而test2.py的import路径是Package.test2,两个点已经高于Package目录了。 这就意味着,绝对导入在某种情况下是错误的,比如在例14中,直接执行test2.py文件是错误的(python test2.py),因为此时test2模块的import路径将会是test2而一个点已经高于它了。

        这看起来很神奇,test2.py文件是否能使相对路径导入同目录的其他文件,取决于其运行方式。这也决定了相对导入是不可能单独使用的,它需要知道当前模块的import路径。

        例14最后的结果显示,test3.py文件被导入后的import路径是Package.test3,这其实也是直接通过test2.py的import路径推断出来的,而与sys.path无关。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2257213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUDA 计时功能,记录GPU程序/函数耗时,cudaEventCreate,cudaEventRecord,cudaEventElapsedTime

为了测试GPU函数的耗时&#xff0c;可以使用 CUDA 提供的计时功能&#xff1a;cudaEventCreate, cudaEventRecord, 和 cudaEventElapsedTime。这些函数可以帮助你测量某个 CUDA 操作&#xff08;如设置设备&#xff09;所花费的时间。 一、记录耗时案例 以下是一个示例程序&a…

数字图像处理(15):图像平移

&#xff08;1&#xff09;图像平移的基本原理&#xff1a;计算每个像素点的移动向量&#xff0c;并将这些像素按照指定的方向和距离进行移动。 &#xff08;2&#xff09;平移向量包括水平和垂直分量&#xff0c;可以表示为&#xff08;dx&#xff0c;dy&#xff09;&#xff…

Hyper-V安装Win11虚拟机并设置vGPU显卡直通

一、为什么我使用Hyper-V虚拟机 我的宿主机是Win11,想装一个Win10或Win11虚拟机。但是我用VMware安装Win10或Win11后,随机地蓝屏,非常烦人,估计是和宿主机的某些设置有关,或者宿主机电脑硬件比较新(我电脑装Win10就会蓝屏,Win11就不会),某些特性不支持。 所以我就安…

Qt Xlsx安装教程

Qt Xlsx安装教程 安装perl 如果没有安装perl&#xff0c;请参考perl Window安装教程 下载QtXlsxWriter源码 下载地址 ming32-make编译32 lib库 C:\Qt\Qt5.12.12\5.12.12\mingw73_32>d: D:\>cd D:\Code\QtXlsxWriter-master\QtXlsxWriter-master D:\Code\QtXlsxWrit…

C# RSA加密和解密,RSA生成私钥和公钥

C# RSA加密和解密&#xff0c;RSA生成私钥和公钥&#xff08;使用XML格式秘钥&#xff09; 目录 前言生成xml格式的公钥和私钥 PrivateKeyPublicKey测试加密、解密 方案1&#xff1a;RSA公钥加密&#xff0c;RSA私钥解密方案2&#xff1a;RSA私钥加密&#xff0c;RSA私钥解密…

【Rive】Android与Rive交互

1 Android与Rive交互的常用接口 1.1 RiveAnimationView参数 <app.rive.runtime.kotlin.RiveAnimationViewandroid:id"id/rive_view"android:layout_width"match_parent"android:layout_height"match_parent"android:adjustViewBounds"…

捷米特 EtherNet/IP 总线协议网关的具体内容介绍

关于EtherNET/IP的基本介绍 EtherNet/IP 中的 “Ethernet” 指以太网&#xff0c;是一种常见的局域网技术&#xff0c;用于在有限区域内实现多台设备之间的数据传输&#xff1b;“IP” 在此处指工业协议&#xff08;Industrial Protocol&#xff09;&#xff0c;而不是通常所说…

Python 读取 Excel 表格并导出为 DBF 文件

以下是将上述代码封装为函数的版本。函数接收 input_excel_path、sheet_name 和 output_dbf_path 作为参数&#xff0c;按照需求读取 Excel 表格并导出为 DBF 文件。 封装函数代码 import pandas as pd import dbfdef excel_to_dbf(input_excel_path, sheet_name, output_dbf_…

使用 ASP.NET Core HttpLoggingMiddleware 记录 http 请求/响应

我们发布了一个应用程序&#xff0c;该应用程序运行在一个相当隐蔽的 WAF 后面。他们向我们保证&#xff0c;他们的产品不会以任何方式干扰我们的应用程序。这是错误的。他们删除了我们几乎所有的“自定义”标头。为了“证明”这一点&#xff0c;我构建了一个中间件&#xff0c…

EasyExcel改名为FastExce做了那些改变呢

回到&#xff1a;github原作者地址&#xff1a;https://github.com/CodePhiliaX/fastexcel 中文 |English | 什么是 FastExcel FastExcel 是由原 EasyExcel 作者创建的新项目。2023 年我已从阿里离职&#xff0c;近期阿里宣布停止更新 EasyExcel&#xff0c;作者他本人决定继…

TCP/IP协议详解(小白)

TCP/IP协议详解 TCP/IP协议包含了一系列的协议&#xff0c;也叫TCP/IP协议族&#xff08;TCP/IP Protocol Suite&#xff0c;或TCP/IP Protocols&#xff09;&#xff0c;简称TCP/IP。TCP/IP协议族提供了点对点的连结机制&#xff0c;并且将传输数据帧的封装、寻址、传输、路由…

【工具】音频文件格式转换工具

找开源资源、下载测试不同库的效果&#xff0c;然后找音频、下载音频、编写代码、测试转换、流程通畅。写一个工具花的时间越来越多了&#xff01;这个 5 天 这个工具是一个音频文件格式转换工具&#xff0c;支持对 mp3.aac.wav.caf.flac.ircam.mp2.mpeg.oga.opus.pcm.ra.spx.…

Vue智慧商城项目

创建项目 vue组件库 — vant-ui&#xff08;常用于移动端&#xff09; Vant 2 - 轻量、可靠的移动端组件库 安装vant npm i vantlatest-v2 -S 引入组件 按需导入和全部导入 全部导入 整个组件库的所有组件都导进来&#xff0c;缺点是增加了代码包体积 main.js import…

探索CSS中的背景图片属性,让你的网页更加美观

导语&#xff1a;在网页设计中&#xff0c;背景图片的运用能够丰富页面视觉效果&#xff0c;提升用户体验。本文将详细介绍CSS中背景图片的相关属性&#xff0c;帮助大家更好地掌握这一技能。 一、背景图片基本属性 1、background-image 该属性用于设置元素的背景图片。语法如…

C#实时监控指定文件夹中的动态,并将文件夹中生成的新图片显示在界面上(相机采图,并且从本地拿图)

结果展示 此类原理适用于文件夹中自动生成图片&#xff0c;并提取最新生成的图片将其显示&#xff0c; 如果你是相机采图将其保存到本地&#xff0c;可以用这中方法可视化&#xff0c;并将检测的结果和图片匹配 理论上任何文件都是可以监视并显示的&#xff0c;我这里只是做了…

通过PS和Unity制作2D动画之一:创建形象

1、通过路径画出轮廓 使用路径的过程中&#xff0c;需要注意&#xff1a; 1&#xff09;如果使用形状工具作图&#xff0c;比如使用椭圆工具画正圆形&#xff0c;需要设置其属性为“路径”。 2&#xff09;使用路径选择工具&#xff0c;再按住Alt键点击某个路径&#xff0c;可…

Spark实训

实训目的: 介绍本实训的基本内容,描述知识目标、,以及本实训的预期效果等。 1、知识目标 (1)了解spark概念、基础知识、spark处理的全周期,了解spark技术是新时代对人才的新要求。 (2)掌握Linux、hadoop、spark、hive集群环境的搭建、HDFS分布文件系统的基础知识与应用…

PDF提取文本

1.环境配置 !pip install PyPDF2 pdfplumber PyPDF2 是用来处理 PDF 文件的库&#xff0c;主要功能包括PDF 文件读取、合并、拆分、旋转&#xff0c;可以从 PDF 中提取纯文本&#xff0c;尽管它的提取效果有限&#xff0c;特别是对于扫描版 PDF 文件。 pdfplumber 是比 PyPDF2…

如何在手机上玩电脑pc游戏,通过termux安装mobox教程说明

如何在手机上玩电脑pc游戏&#xff0c;通过termux安装mobox教程说明 所需软件 1.Termux 或改版 zeroTermux 2.Termux:X11 3.Inputbridge 以下为网盘链接 https://pan.baidu.com/s/1foEY0djqJTCrtYES9nE66g?pwd2ji2 提取码:2ji2 123 网盘 https://www.123pan.com/s/l5mlV…

create-react-app react19 搭建项目报错

报错截图 此时运行会报错&#xff1a; 解决方法&#xff1a; 1.根据提示安装依赖法 执行npm i web-vitals然后重新允许 2.删除文件法 在index.js中删除对报错文件的引入&#xff0c;删除报错文件