详解Python中的路径问题


Posted in Python onSeptember 02, 2020

1. 绝对路径引入

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

import sys
print(sys.path)

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

export PYTHONPATH=/opt/python:$PYTHONPATH
echo $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 abc
from .abc import fool
from ..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:\PythonLearning\TestIm\main.py", line 3, in <module>
from Tom import tom
File "D:\PythonLearning\TestIm\Kate\kate.py", line 4, in <module>
from .. import kate
ValueError: 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 相关文章推荐
从零学python系列之数据处理编程实例(二)
May 22 Python
Python中的两个内置模块介绍
Apr 05 Python
简单介绍Python中的JSON使用
Apr 28 Python
Python学习入门之区块链详解
Jul 25 Python
使用Python从零开始撸一个区块链
Mar 14 Python
Python3和pyqt5实现控件数据动态显示方式
Dec 13 Python
Pycharm激活方法及详细教程(详细且实用)
May 12 Python
解决numpy矩阵相减出现的负值自动转正值的问题
Jun 03 Python
python中关于数据类型的学习笔记
Jul 19 Python
Python大批量搜索引擎图像爬虫工具详解
Nov 16 Python
Pytorch自定义Dataset和DataLoader去除不存在和空数据的操作
Mar 03 Python
Python中常见的导入方式总结
May 06 Python
python dict如何定义
Sep 02 #Python
python基本算法之实现归并排序(Merge sort)
Sep 01 #Python
在pycharm中文件取消用 pytest模式打开的操作
Sep 01 #Python
Python内置函数property()如何使用
Sep 01 #Python
mac安装python3后使用pip和pip3的区别说明
Sep 01 #Python
python3.7.3版本和django2.2.3版本是否可以兼容
Sep 01 #Python
解决python便携版无法直接运行py文件的问题
Sep 01 #Python
You might like
全国FM电台频率大全 - 25 云南省
2020/03/11 无线电
PHP字符转义相关函数小结(php下的转义字符串)
2007/04/12 PHP
PHP中的float类型使用说明
2010/07/27 PHP
ThinkPHP分页实例
2014/10/15 PHP
如何实现JS函数的重载
2006/09/22 Javascript
实现复选框全选/全不选切换
2006/12/23 Javascript
使用javascript创建快捷方式的简单实例
2013/08/09 Javascript
js给页面加style无效果的解决方法
2014/01/20 Javascript
基于JS代码实现图片在页面中旋转效果
2016/06/16 Javascript
使用node.js中的Buffer类处理二进制数据的方法
2016/11/26 Javascript
小程序开发实战:实现九宫格界面的导航的代码实现
2017/01/19 Javascript
利用nodejs监控文件变化并使用sftp上传到服务器
2017/02/18 NodeJs
微信小程序五子棋游戏的棋盘,重置,对弈实现方法【附demo源码下载】
2019/02/20 Javascript
页面内锚点定位及跳转方法总结(推荐)
2019/04/24 Javascript
JavaScript Math对象和调试程序的方法分析
2019/05/13 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
Python实现将HTML转换成doc格式文件的方法示例
2017/11/20 Python
使用Python读取大文件的方法
2018/02/11 Python
Python设计模式之模板方法模式实例详解
2019/01/17 Python
pandas计算最大连续间隔的方法
2019/07/04 Python
对Django中的权限和分组管理实例讲解
2019/08/16 Python
Python SQLAlchemy入门教程(基本用法)
2019/11/11 Python
Python在centos7.6上安装python3.9的详细教程(默认python版本为2.7.5)
2020/10/15 Python
html5中如何将图片的绝对路径转换成文件对象
2018/01/11 HTML / CSS
瑰珀翠美国官网:Crabtree & Evelyn美国
2016/11/29 全球购物
Max&Co官网:意大利年轻女性时尚品牌
2017/05/16 全球购物
任意存:BOXFUL
2018/05/21 全球购物
荷兰家电销售网站:Welhof
2020/12/08 全球购物
中东奢侈品购物网站:Ounass
2020/09/02 全球购物
学校花圃的标语
2014/06/18 职场文书
党的群众路线教育实践活动对照检查材料(个人)
2014/09/24 职场文书
教学督导岗位职责
2015/04/10 职场文书
项目技术负责人岗位职责
2015/04/13 职场文书
个人业务学习心得体会
2016/01/25 职场文书
Golang 并发下的问题定位及解决方案
2022/03/16 Golang
MongoDB支持的索引类型
2022/04/11 MongoDB