类似于系统路径,我想在我的代码中提供一些便利,允许用户指定一个可能位于少数路径之一的文件名。
说我有两个或多个配置路径
['~/.foo-config/', '/usr/local/myapp/foo-config/']
我的用户想打开bar
,(又称bar.baz
)
是否有方便的构建方式让open('bar')
或open('bar.baz')
自动以优先级的LTR顺序搜索这些文件?例如,临时调整我的sys.path
才能为我这样做吗?其他,您如何建议实现类似路径的搜索开放式交换器?
正如其他人已经提到的那样: 我建议以优先顺序和打开文件的顺序分开搜索路径的逻辑,因为这样,更容易 test> test 和 read 。 我会做这样的事情: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()
open
没有进入这种逻辑。如果需要,请编写一个使用os.path.join
将sys.path
的每个成员连接到参数文件名的包装函数,并试图按顺序打开它们,并处理未找到此类文件时发生的错误。
我会添加,正如另一个用户所述,这是对sys.path
的滥用,但是此功能可用于任何路径列表。实际上,也许最好的选项是使用另一个用户建议的环境变量来指定符合结肠列表的配置目录列表,然后您将其解析并在搜索功能中使用。
环境变量
说您的应用程序名为foo ...在读书中,请告诉用户使用foo_path环境变量来指定额外的路径
然后在您的应用程序内部执行
之类的事情 for path in os.environ.get("FOO_PATH",".").split(";"):
lookfor(os.path.join(path,"somefile.txt"))
您可以将其包装到通用功能
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()
从Python标准库文档提取的开放式内置功能:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
...文件是要打开的文件名(绝对或)的字符串或字节对象(绝对或)要打开...
明确地,打开不会带任何东西自动找到一个文件:如果路径不是绝对的,则仅在当前目录中搜索。
因此,您必须使用自定义功能或自定义类。例如:
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)
这意味着文件开启器将保留其自己的路径,默认情况下将使用当前路径初始化,将具有设置,附加或扩展其路径的方法,并将升级formany file filenotfounderror是在其路径中列出的任何目录中都找不到文件。
用法:
o = path_opener(['~/.foo-config/', '/usr/local/myapp/foo-config/'])
with o.open('foo') as fd:
...