在打开文件进行写入操作之前,递归创建目录。

4

我需要将内容写入文件(截断),但是文件路径本身可能不存在。例如,我想要将内容写入/tmp/a/b/c/config,但是/tmp/a本身可能不存在。因此,open('/tmp/a/b/c/config', 'w')显然无法工作,因为它不会创建必要的目录。然而,我可以使用下面的代码:

import os

config_value = 'Foo=Bar'  # Temporary placeholder

config_dir = '/tmp/a/b/c'  # Temporary placeholder
config_file_path = os.path.join(config_dir, 'config')

if not os.path.exists(config_dir):
    os.makedirs(config_dir)

with open(config_file_path, 'w') as f:
    f.write(config_value)

有没有更Pythonic的方法来做这件事?最好能知道Python 2.x和Python 3.x两种版本的方法(即使我在我的代码中使用2.x,由于依赖原因)。

1个回答

2

如果您在多个地方重复使用此模式,您可以创建自己的上下文管理器来扩展open()并重载__enter__()

import os

class OpenCreateDirs(open):
    def __enter__(self, filename, *args, **kwargs):
        file_dir = os.path.dirname(filename)
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)

        super(OpenCreateDirs, self).__enter__(filename, *args, **kwargs)

那么你的代码就变成了:
import os

config_value = 'Foo=Bar'  # Temporary placeholder
config_file_path = os.path.join('/tmp/a/b/c', 'config')

with OpenCreateDirs(config_file_path, 'w') as f:
    f.write(config_value)

当你运行with open(...) as f:时,被调用的第一个方法是open.__enter__()。因此,在调用super(...).__enter__()之前创建目录,可以在尝试打开文件之前创建目录。

好的,非常感谢:)嗯,这只是一个特例(在当前情况下),我觉得这是很多人都遇到的常见模式,所以我才首先提出了这个问题。然而,使用上下文管理器可以帮助我长期解决这个问题。 - Jay Bosamiya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接