1

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

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

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

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

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

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

4

4 回答 4

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()
于 2015-05-08T17:54:48.497 回答
1

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

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

于 2015-05-08T17:46:34.860 回答
0

environmental variables

say your app is named foo ... in the readme tell the user to use the FOO_PATH environmental variable to specify the extra paths

then inside your app do something like

 for path in os.environ.get("FOO_PATH",".").split(";"):
     lookfor(os.path.join(path,"somefile.txt"))

you could wrap it into a generic function

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")

then you could use it just like normal open

with open_foo("my_config.txt") as f:
     print f.read()
于 2015-05-08T17:44:54.093 回答
0

从 Python 标准库文档中提取开放内置函数

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

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

明确地说, open 不会带来任何东西来自动查找文件:如果路径不是绝对的,则仅在当前目录中搜索。

因此,您将不得不为此使用自定义函数或自定义类。例如:

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 is a file is not found in any of the在其路径中列出的目录。

用法 :

o = path_opener(['~/.foo-config/', '/usr/local/myapp/foo-config/'])
with o.open('foo') as fd:
    ...
于 2015-05-08T18:30:55.527 回答