raise IOError('The file is not exist!')

文件的读取路径通常有三种,如下:

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方式

猜你喜欢

转载自blog.csdn.net/rhx_qiuzhi/article/details/80371239