文件的读取路径通常有三种,如下:
if __name__ == '__main__':
#y = r"F:\py_test\Framework\config\config.yaml" #1
#y = "F:/py_test/Framework/config/config.yaml" #2
#y = 'config.yaml' #3
here = os.path.dirname(os.path.dirname(__file__))
print here
y = os.path.join(here, '../config/config.yaml') #4
print y
reader = YamlReader(y)
print(reader.data)
因为“\”在python有转义的作用,所以这里需要使用"r”,防止转义,但是无论是第一种使用“r”还是第二种很pythonic的读取方式还是,均不行。
鉴于使用绝对的路径引发的问题,这里极爱那个配置文件 config.yaml拷贝到和本脚本一个目录下,这样才可以正确读取,但是为了实现配置文件和支持代码(读取配置文件的类)进行分离,实现层级划分,显然这不是解决办法。参考Python ConfigParser cannot search .ini file correctly使用文件目录拼接的方式os.path.join的方法。配置文件config.yaml目录:
here = os.path.dirname(os.path.dirname(__file__))
print here
y = os.path.join(here, '../config/config.yaml')
print y
输出结果仍存在问题:
但是通过打印发现其实config.yaml文件就在F:py_test/Framework\../config/目录下,由于这里已经是绝对路径了,因此应该是当前目录“.”,而不应该使用上一级目录“..”,所以进行修改
#coding:utf-8
#file_reader.py
import yaml
import os
class YamlReader:
def __init__(self, yamlf):
if os.path.exists(yamlf):
self.yamlf = yamlf
else:
#raise FileNotFoundError('文件不存在!')FileNotFoundError为python3使用的文本不存在异常处理方法
raise IOError('The file is not exist!')
self._data = None
@property
def data(self):
# 如果是第一次调用data,读取yaml文档,否则直接返回之前保存的数据
if not self._data:
with open(self.yamlf, 'rb') as f:
self._data = list(yaml.safe_load_all(f)) # load后是个generator,用list组织成列表
return self._data
here = os.path.dirname(os.path.dirname(__file__))
y = os.path.join(here, '../config/config.yaml')
if __name__ == '__main__':
#y = r"F:\py_test\Framework\config\config.yaml"
#y = "F:/py_test/Framework/config/config.yaml"
#y = 'config.yaml'
here = os.path.dirname(os.path.dirname(__file__))
#print here
y = os.path.join(here, './config/config.yaml')
#print y
reader = YamlReader(y)
print(reader.data)
输出结果:
为了彻底理解路径的问题,再次进行验证:
BASE_PATH = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
print BASE_PATH
CONFIG_FILE = os.path.join(BASE_PATH, config, config.yml) #1
print CONFIG_FILE
here = os.path.dirname(os.path.dirname(__file__))
CONFIG_FILE = os.path.join(here, './config/config.yaml')
print CONFIG_FILE
提示#1存在错误:
修改之后,将拼接的路径作为字符串元素进行引用
CONFIG_FILE = os.path.join(BASE_PATH, 'config', 'config.yml')
发现本意是输出config.yaml文件,但是路径显示的不同,第二个中是以windows的方式打印出文件的路径,而第三种方式才是需要的pythonic方式.这里的差别在于BATH_PATH使用的是os.path.abspath,而here使用的是os.path.dirname,那能否将BASE_PATH的获取路径也修改为os.path.dirname呢?
#BASE_PATH = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
print BASE_PATH
CONFIG_FILE = os.path.join(BASE_PATH, 'config', 'config.yml')
print CONFIG_FILE
here = os.path.dirname(os.path.dirname(__file__))
CONFIG_FILE = os.path.join(here, './config/config.yaml')
print CONFIG_FILE
发现只完成了BASE_PATH所在路径的“修改”,但是文件路径并没有pythonic,因此使用绝对路径一定要慎重。当然这里既然已经知道目录层级关系,通过dirname获取工程的目录(根目录),在通过join将子目录和根目录结合在一起,可以去掉目录读取中的"../"或者"./",即修改如下:
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
CONFIG_FILE = os.path.join(BASE_PATH, 'config/config.yaml')
print CONFIG_FILE
输出中不难发下,路径连接的方式红色框中的为window下路径层级的连接方式,其余的为pythonic方式