关于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字符串中要使用'\'时有两种方法: 使用 ...
随机推荐
- Lua CallbackHell优化
概述 在异步操作中,常常要使用回调.但是,回调的嵌套常常会导致逻辑混乱,一步错步步错,难以维护.在Lua中,可以使用协程进行优化. 问题分析 模拟一个回合制游戏攻击过程 local function ...
- MySQL8.0报错:Access denied; you need (at least one of) the SYSTEM_USER privilege(s) for this operation
MySQL8.0.16版本中新增了一个system_user帐户类型,当新增用户并赋予权限时 mysql> create user 'proxysql'@'192.168.20.%' ident ...
- ProxySQL(1):简介和安装
文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9278818.html ProxySQL有两个版本:官方版和percona版,percona版是在官方版的基础 ...
- Kubernetes HPA 使用详解
文章转载自:https://www.qikqiak.com/post/k8s-hpa-usage/ Kubernetes 提供了这样的一个资源对象:Horizontal Pod Autoscaling ...
- Kibana探索数据(Discover)
总结说明: 1.先在Management/Kibana/Index Patterns 界面下添加索引模式(前提是有索引数据) 2.在Discover界面选中响应的索引模式 3.开启Kibana 查询语 ...
- aardio + PowerShell 可视化快速开发独立 EXE 桌面程序
aardio 可以方便地调用 PowerShell ,PowerShell 中也可以自由调用 aardio 对象与函数.不用带上体积很大的System.Management.Automation.dl ...
- 对循环神经网络参数的理解|LSTM RNN Input_size Batch Sequence
在很多博客和知乎中我看到了许多对于pytorch框架中RNN接口的一些解析,但都较为浅显甚至出现一些不准确的理解,在这里我想阐述下我对于pytorch中RNN接口的参数的理解. 我们经常看到的RNN网 ...
- Linux自动切换用户
Linux自动切换用户 一.创建sh文件 touch su_user.sh 二.下载脚本 yum install -y expect 三.脚本内容 #!/bin/bash# This is our f ...
- iptables基本使用举例
一.链的基本操作 1.清除所有的规则. 1)清除预设表filter中所有规则链中的规则. # iptables -F 2)清除预设表filter中使用者自定链中的规则. #iptables -X #i ...
- iptables使用详解
iptables使用详解 @(linux)[iptables] 前言 最近买了一个VPS,并在上面搭了DOCKER,然后再DOCKER中安装Mysql.但只要将网络端口映射到宿主机上,那么外部网络就可 ...