您的位置:首页技术文章
文章详情页

详解Python中的路径问题

【字号: 日期:2022-07-12 15:22:14浏览:2作者:猪猪

1. 绝对路径引入

Python 在搜索模块时,依次搜索sys.path里的位置,直到找到模块为止。下面命令可以查看当前的搜索路径:

import sysprint(sys.path)

sys.path的初始值来源于两个(其实还有一些更复杂但不常用的)。一个是系统的PYTHONPATH变量,因此可通过设置该变量,来设置 Python 默认的搜索位置。比如:

export PYTHONPATH=/opt/python:$PYTHONPATHecho $PYTHONPATH

将该命令放在系统初始化脚本(/etc/environment)或者 BASH 初始化脚本(/~/.bashrc)里,可以对每个新开的窗口有效。

sys.path的另一个来源是当前执行程序所在的目录 (而不是当前目录)。比如当前目录下文件夹./cc下有一个b.py,那么执行./cc/b.py时,./cc(而不是./!)将被加到sys.path:

python ./cc/b.py

2. 相对路径引用

上面说的是搜索模块都是指绝对路径引用。对于非系统目录,就需要操纵sys.path。但操纵sys.path有外溢效果,因为它是一个全局变量。对于同一个库里的模块的互相引用,可以考虑使用相对路径:

from . import abcfrom .abc import foolfrom ..up import foo

但相对路径有两个很恶心的问题,使得用法极为受限。其中一个是:

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always __main__, modules intended for use as the main module of a Python application should always use absolute imports.

包含相对路径 import 的 python 脚本不能直接运行,只能作为 module 被引用。原因正如手册中描述的,所谓相对路径其实就是相对于当前 module 的路径,但如果直接执行脚本,这个 module 的 name 就是__main__, 而不是 module 原来的 name , 这样相对路径也就不是原来的相对路径了,导入就会失败。

在使用相对引用的文件中,不能有 __main__ 方法,只执行作为一个 module 进行引用,而不是直接执行脚本。

举个简单例子。假设./cc/目录下已有一个./cc/b.py(内容为空)。当前目录下的./a.py内容为:

from .cc import b

那么直接运行python ./a.py将会报错:

ModuleNotFoundError: No module named ’__main__.cc’; ’__main__’ is not a package

另一个是常见的错误是: ValueError: attempted relative import beyond top-level package。

在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。

文件夹被python解释器视作package需要满足两个条件:

1、文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。

2、不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。

补充:在'from YY import XX'这样的代码中,无论是XX还是YY,只要被python解释器视作package,就会首先调用该package的__init__.py文件。如果都是package,则调用顺序是YY,XX。

另外,练习中“from . import XXX”和“from .. import XXX”中的’.’和’..’,可以等同于linux里的shell中’.’和’..’的作用,表示当前工作目录的package和上一级的package。

举个例子:

testIm/--__init__.py--main.py : from Tom import tom--Tom/--__init__.py : print('I’m Tom’s __init__!')--tom.py : from . import tomBrother, from .. import kate,print('I’m Tom!')--tomBrother.py print(I’m Tom’s Brother!)--Kate/--__init__.py : print('I’m Kate’s __init__!')--kate.py

运行文件:main.py

结果:

I’m Tom’s __init__!I’m Tom’s Brother!Traceback (most recent call last):File 'D:PythonLearningTestImmain.py', line 3, in <module>from Tom import tomFile 'D:PythonLearningTestImKatekate.py', line 4, in <module>from .. import kateValueError: attempted relative import beyond top-level package>>>

可以看到from . import tomBrother顺利执行,首先执行了Tom文件夹下的__init__.py文件,后来执行了tomBrother.py文件,但是当执行到“from .. import kate”时报错,这是因为我们是在TestIm文件夹下把main.py文件作为主函数的入口执行的,因此尽管TestIm文件夹中有__init__.py文件,但是该文件夹不能被python解释器视作package,即Tom package不存在上层packge,自然会报错,相对导入时超出了最高层级的package。

修改方法:

test/--main.py : from testIm.Tom import tom--testIm/--__init__.py--Tom/--__init__.py : print('I’m Tom’s __init__!')--tom.py : from . import tomBrother, from .. import Kate,print('I’m Tom!')--tomBrother.py print(I’m Tom’s Brother!)--Kate/--__init__.py : print('I’m Kate’s __init__!')--kate.py

运行文件:main.py

结果:

I’m top’s __init__!I’m Tom’s __init__!I’m Tom’s Brother!!I’m Kate’s __init__!I’m Tom!

即主函数入口不在TestIm中,则TestIm和其同样包含__init__.py文件的子文件夹都被python解释器视作package,形成相应的嵌套关系。可以正常使用from . import XXX和from .. import XXX。

以上就是详解Python中的路径问题的详细内容,更多关于Python 路径的资料请关注好吧啦网其它相关文章!

标签: Python 编程
相关文章: