关于python路径的问题思考
我相信你肯定遇到过这样的报错
Traceback (most recent call last):
File "main.py", line 549, in <module>
os.chdir(os.path.dirname(__file__))
FileNotFoundError: [Errno 2] No such file or directory: ''
这还要从python的路径问题说起
首先我们了解一下几个重要的概念

这里的 Desktop 指的是运行路径
寻找python 脚本的方式是相对路径寻找
__file__ 变量值为 path_test/test.py
知道这些我下面具体说 运行路径不同 会导致的问题
运行路径不同导致的问题
举一个简单的例子

在这个项目中有一个 1.txt 里面包含 Hello world字符串, 这段程序就是简单的寻找然后并输出,正常是可以输出的像这样在 sublime 中运行,得到结果:

而我们以另一种方式运行:

这样就会提示找不到这个文件,为什么会有这样的问题?
这里出现这种状况的原因主要是因为运行路径不同,而寻找相对路径的 1.txt 文件也就不同。
第一种寻找的 1.txt 真正路径是在 /home/wshuo/Desktop/path_test/1.txt
而第二种寻找的 1.txt 的真正路径是在 /home/wshuo/Desktop/1.txt 这当然会找不到了
这是因为 sublime 运行脚本的时候首先会将脚本存在的路径作为运行路径, 而第二种在终端运行的时候,会把当前所在的路径作为运行路径(我所在的是 Desktop)
下面我简单写一个例子来证明以上两点说法:


os.getcwd() 这个路径可以获取到当前的路径(也就是程序运行的路径)
运行路径不同找不到文件的解决方案
- 第一种你可以把 修改
txt文本文件改为绝对路径,显然这不是好的解决办法,因为代码不一定存放在什么地方,写成绝对路径寻找txt文件绝对是很傻的解决方案 - 更改运行的路径, 无论在什么路径运行都更改到项目路径下运行,这样无论 整个项目存放在什么地方都可以找到
txt文件了
那么如何更改我们的运行路径呢?
我猜大部分都是这样写的
import os
print(__file__)
path = os.path.dirname(__file__)
print(path)
os.chdir(path)
print(os.getcwd())
with open('1.txt') as f:
s = f.read()
print(s)
__file__ 的意思是 寻找这个脚本的路径+这个脚本文件的名字(可以是绝对路径寻找或相对路径寻找)
os.path.dirname 这个函数可以取出文件所在的路径
os.chardir 更改运行路径,下面我再使用这两种方式运行这段代码
所以上面代码的作用就可以解决 无论运行路径是否在脚本所在的路径都可以更改为脚本所在的路径


可以看到就算运行路径不在项目路径也不会报错了
更改运行路径导致的其他问题
但是问题真的就解决了吗?
下面我们换一种运行方式来运行
可以看到,更改完的代码进入项目路径运行反而会出错,而我们也可以看到 __file__ 变为了 test.py
这里报错是因为 __file__ 没有路径了完全就是一个文件名字了,所以肯定就获取不到他的父级目录了,而这段代码为什么在 sublime 运行的时候没有报错? 不应该他们运行的路径都是项目路径吗?
我们来看另一种运行方式(可能看到这里你已经懵逼了,但是其实我后面会做一个总结看完总结在看这些一下子就清晰明了了)

可以看到这里我们又没有报错了,因为这里我们寻找这个脚本文件是绝对路径寻找的!
前面我一直再说运行路径 不同导致的问题,这里引入一个新的概念:寻找脚本的方式 绝对路径寻找 和相对路径寻找
python运行方式分类
| 运行媒介 | 运行路径 | 寻找脚本的方式 |
|---|---|---|
| ide 运行 | 文件所在路径 | 绝对路径寻找 |
| 双击脚本文件 | 文件所在路径 | 绝对路径寻找 |
| cmd 或终端运行 | 不确定,看当前所在的路径 | 绝对路径寻找或相对路径寻找 |
可以看到 在终端或 cmd 中运行脚本的时候是最灵活的了,而我们可以以相对路径寻找和绝对路径寻找运行脚本, 运行路径也可以随着当前所在的路径不同而不同,所以用os.chdir上面修改过的代码可以在
| 运行路径 | 寻找脚本的方式 |
|---|---|
| 任意 | 至少有一级父级目录的相对路径寻找或直接的绝对路径寻找 |
这种条件下运行成功,因为如果进入项目路径下运行的话就必须有至少一层父级路径可以提供,否则获取不到父级路径,也就更改不了运行路径(报错是在获取不到父级目的地方报错)
知道报错原因,你也可以在项目路径这样运行脚本
wshuo@wshuo-Aspire-F5-572G:~/Desktop/path_test$ python3 ../path_test/test.py
Hello world!
这样也不会报错,就是退到上级目录然后在进入项目目录运行,这样就可以获取到文件所在的目录了,但是很傻,我们又不能确定用户会不会在文件所在目录运行这个脚本,更不会确定用户会不会以这样的方式运行脚本
最终的解决办法
- 做一个简单的容错处理
import os
try:
os.chdir(os.path.dirname(__file__))
except:
pass
with open('1.txt') as f:
s = f.read()
print(s)
这种解决方案肯定包含了所有情况,因为只有当 运行路径为 项目路径时 且python 后面只有 test.py 这个文件名的时候 才会报错,但在这种情况下根本不需要考虑更改运行路径的问题, 因为运行路径已经是 项目路径了,肯定是可以找到 1.txt 文件的
- 用
os.path.abspath处理一下再获取脚本所在路径
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
with open('1.txt') as f:
s = f.read()
print(s)
这种解决方案也是不管 __file__ 这个变量是只是一个文件名经过获取绝对路径都可以变成绝对路径+文件名 的形式, 这样再获取脚本所在的路径肯定也不会报错的
关于python路径的问题思考的更多相关文章
- Mac Python路径总结
Mac 下Python 可以多版本的并存,并且Python的目录也有好几个,不过总体来说,Mac 自带的有python 还是比较方便的 Mac 系统自带的又Python ,可能Python版本需要更新 ...
- 沉淀,再出发:python爬虫的再次思考
沉淀,再出发:python爬虫的再次思考 一.前言 之前笔者就写过python爬虫的相关文档,不过当时因为知识所限,理解和掌握的东西都非常的少,并且使用更多的是python2.x的版本的功能,现 ...
- Python开发环境Wing IDE设置Python路径详解
在使用Wing IDE的时候,Python源代码取决于PYTHONPATH(无论是外部或通过内部改变sys.path系统设置),用户需要将路径设置到Wing IDE中. 这个值可以从项目菜单和工具栏的 ...
- Spring中统一相同版本的api请求路径的一些思考
Spring中统一相同版本的api请求路径的一些思考 问题场景 当我们在实际开发中,可能会遇到开发相同同版本的api, 假设相同版本的api请求路径为/v1/functionA,/v1/functio ...
- python - 路径处理 和 模块导入
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: study_模块导入.py@ide: PyCharm Community E ...
- pycharm怎么修改python路径
今天安装Django的时候遇到了python版本冲突,找不到python路径,所以又重新安装了一个python3.6.5 安装完之后,突然发现自己的pycharm是之前Anaconda的3.5版本,那 ...
- python路径写入注册表,导入三方模块win32
python在安装第三方模块时候,需要将python的路径写入注册表,否则会提示 'python version 3.8-32 required,which was not found in the ...
- 查找默认安装的python路径,并输出到 FindPythonPathX_output.txt
在python程序设计教学中,在汉化IDEL时.为PyCharm项目设置解释器时,经常需要查找python安装路径.对老手来说很简单,但对很多刚开始学习编程的学生来说,则很困难.所以,编写了一个批处理 ...
- python 路径操作工具 pathlib,比 os 模块好用太多
在 python 当中,如果你想控制路径,基本上绕不开 os.path.我希望看完这篇文章以后,熟练使用 python 的你能立刻开始使用 pathlib 模块,一刻也不要耽误. pathlib 相对 ...
- Python路径总结
Windows下文件路径的分隔符是'\'反斜杠,文件路径也是一个字符串,牵扯到'\'在Python字符串中存在转义的情况,就对这个问题做一个探究. Python字符串中要使用'\'时有两种方法: 使用 ...
随机推荐
- Ceph 存储集群第一部分:配置和部署
内容来源于官方,经过个人实践操作整理,官方地址:http://docs.ceph.org.cn/rados/ 所有 Ceph 部署都始于 Ceph 存储集群. 基于 RADOS 的 Ceph 对象存储 ...
- Go实现优雅关机与平滑重启
前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式.而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出 ...
- Activate MFA报错:MFADevice entity at the same path and name already exists
MFA即:Multi-factor authentication (MFA) 今天在为自己账号Activate MFA时报错,如下图所示: Entity already exists This ent ...
- 利用FastReport传递图片参数,在报表上展示签名信息
在一个项目中,客户要求对报表中的签名进行仿手写的签名处理,因此我们原先只是显示相关人员的姓名的地方,需要采用手写方式签名,我们的报表是利用FastReport处理的,在利用楷体处理的时候,开发展示倒是 ...
- Android自动化测试工具调研
原文地址:Android自动化测试工具调研 - Stars-One的杂货小窝 Android测试按测试方式分类,可分为两种:一种是传统逻辑单元测试(Junit),另外一种则是UI交互页面测试. 这里详 ...
- http://localhost:8282/user/findsomeuser[object%20Object]
查看vue中的方法的访问路径是否填写正确. 后端:
- 15 Uncaught TypeError: Cannot set properties of null (setting ‘onclick‘)
1.报错的代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...
- Sentinel 介绍与下载使用
sentinel 前方参考 计算QPS-Sentinel限流算法 https://www.cnblogs.com/yizhiamumu/p/16819497.html Sentinel 介绍与下载使用 ...
- LcdTools如何通过PX01把EDP屏的EDID拷贝出来
PX01点EDP屏在上电过程会自动读取屏EDID,怎么把EDP EDID值拷贝出来呢? 在上电时序函数调用SetEdidRdShowEn(ON)指令开启EDID值读取显示功能.如下图 通过上述操作开机 ...
- JSP Webshell免杀设计
JSP Webshell免杀设计 @author:drag0nf1y 介绍 什么是Webshell? 被服务端解析执行的php.jsp文件 什么是RCE? remote command execute ...