Python从自定义PATH打开文件名

时间:2015-05-08 17:40:12

标签: python file search system-paths

与系统路径类似,我想在我的代码中提供一些便利,允许用户指定一个文件名,该文件名可能位于少数路径之一。

假设我有两个或更多配置路径

['~/.foo-config/', '/usr/local/myapp/foo-config/']

我的用户想要打开bar,(AKA bar.baz

  1. 是否有方便的构建让open('bar')open('bar.baz')以LTR优先顺序自动搜索该文件的路径?例如,是否会临时调整我的sys.path只是这些目录为我做这个吗?

  2. 否则,您如何建议实施类似PATH的搜索开放包装?

4 个答案:

答案 0 :(得分:2)

正如其他人已经提到的那样:sys.path 只影响模块搜索路径,即它与导入Python模块相关,但对于open()则完全没有。

我建议按优先顺序分开搜索路径的逻辑并打开文件,因为这样更容易测试读取

我会做这样的事情:

import os

PATHS = ['~/.foo-config/', '/usr/local/myapp/foo-config/']


def find_first(filename, paths):
    for directory in paths:
        full_path = os.path.join(directory, filename)
        if os.path.isfile(full_path):
            return full_path


def main():
    filename = 'file.txt'
    path = find_first(filename, PATHS)
    if path:
        with open(path) as f:
            print f
    else:
        print "File {} not found in any of the directories".format(filename)


if __name__ == '__main__':
    main()

答案 1 :(得分:1)

open没有进入那种逻辑。如果需要,编写一个包装函数,使用os.path.joinsys.path的每个成员连接到参数文件名,并尝试按顺序打开它们,处理没有找到此类文件时发生的错误。

我补充说,正如另一位用户所说,这是对sys.path的误用,但此功能适用于任何路径列表。实际上,最好的选择可能是使用另一个用户建议的环境变量来指定以冒号分隔的配置目录列表,然后在搜索功能中对其进行解析和使用。

答案 2 :(得分:0)

环境变量

说你的应用程序名为foo ...在自述文件中告诉用户使用FOO_PATH环境变量来指定额外的路径

然后在您的应用内部执行类似

的操作
def open_foo(fname):
   for path in os.environ.get("FOO_PATH",".").split(";"):
       path_to_test = os.path.join(path,"somefile.txt")
       if os.path.exists(path_to_test):
              return open(path_to_test)
   raise Exception("No File Found On FOOPATH")

你可以将它包装成通用函数

with open_foo("my_config.txt") as f:
     print f.read()

那么你可以像普通的开放一样使用它

{{1}}

答案 3 :(得分:0)

从{标准库}文档中提取open built-in function

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

... file是字符串或字节对象,提供要打开的文件的路径名(绝对或相对于当前工作目录)...

显然,open不会带来任何自动查找文件的内容:如果path不是绝对的,则只在当前目录中搜索。

因此,您必须使用自定义函数或自定义类。例如:

class path_opener(object):
    def __init__(self, path = [.]):
        self.path = path
    def set(self, path):
        self.path = path
    def append(self, path):
        self.path.append(path)
    def extent(self, path):
        self.path.extend(path)
    def find(self, file):
        for folder in self.path:
            path = os.path.join(folder, file)
            if os.path.isfile(path):
                return path
        raise FileNotFoundError()
    def open(self, file, *args, **kwargs):
        return open(self.find(file), *args, **kwargs)

这意味着文件开启器将保留其自己的路径,默认情况下将使用当前路径进行初始化,将具有设置,追加或扩展其路径的方法,并将正常引发FileNotFoundError是在其路径中列出的任何目录中找不到的文件。

用法:

o = path_opener(['~/.foo-config/', '/usr/local/myapp/foo-config/'])
with o.open('foo') as fd:
    ...