【问题标题】:Open file for read/write, create if needed打开文件进行读/写,根据需要创建
【发布时间】:2014-04-04 05:37:27
【问题描述】:

打开文件最优雅的方式是什么

  • 如果文件不存在,则会创建该文件,
  • 如果文件确实存在,则不会被截断并且
  • 是否可以写入文件的任何部分(查找后),而不仅仅是结尾?

据我所知,the open builtin 似乎无法胜任这项任务:它提供了多种模式,但我尝试的每一种模式都无法满足我的至少一项要求:

  • 如果文件不存在,r+ 将失败。
  • w+ 将截断文件,丢失所有现有内容。
  • a+ 将强制所有写入到文件末尾,至少在我的 OS X 上是这样。

在打开文件之前检查是否存在感觉很糟糕,因为它为竞争条件留出了空间。这同样适用于在异常处理程序中以不同的模式重试打开。希望有更好的办法。

【问题讨论】:

  • 如果你的目标是写到文件的中间,我怀疑有没有很干净的方法。

标签: python file-io python-3.x io posix


【解决方案1】:

您需要使用os.open() 在操作系统中低于open() 允许的级别打开它。特别是,将os.RDWR | os.O_CREAT 传递为flags 应该可以满足您的要求。有关详细信息,请参阅 open(2) 手册页。然后您可以将返回的 FD 传递给 os.fdopen() 以从中获取文件对象。

【讨论】:

  • 特别是结合os.fdopen,这看起来非常好。我刚刚在相关链接中找到了 abot this answer,这表明相同。谢谢!
  • 我尝试了fd = os.open('.pree_config', os.O_RDWR | os.O_CREAT) config_file = os.fdopen(fd),但我得到了io.UnsupportedOperation: not writable 错误。我通过将 'r+' 参数传递给 os.fdopen()... 解决了这个问题
【解决方案2】:

如果你使用的是Python 3.3+,可以使用x模式(独占创建模式):

try:
    f = open('/path/to/file', 'x+')
except FileExistsError:
    f = open('/path/to/file', 'r+')

如果文件已经存在,它会引发FileExistsError

【讨论】:

    【解决方案3】:

    我可能错了,但我不认为如果没有多个线程并且tryexcept 块是同一个线程,就会出现竞争条件? (真的可以做多线程吗?)

    这应该取决于任务。

    >>>try: 
          f=open('myfile.txt','r')
       except OSError:
          f=open('myfile.txt','w')
       finally:
          #whatever file I/O you need.
    

    【讨论】:

    • 我担心多个应用程序,其中一些可能使用不同的代码。
    • “在异常处理程序中以不同的模式重试打开也是如此。”无论 Python 脚本中是否使用线程,竞争条件都可能发生在其他程序中。
    • @IgnacioVazquez-Abrams 我不关注,其他程序正在尝试访问该文件?那么不应该在 that 程序而不是 Python 脚本中进行检查吗?我可能遗漏了一些非常明显的东西。
    • @IgnacioVazquez-Abrams 无论如何,您的回答似乎已经涵盖了它。 +1
    • 一个漏洞可以尝试利用open()调用例如链接到系统文件,在进程中销毁它。
    【解决方案4】:

    我在尝试将项目作为字典转储到文件时遇到了类似的问题。但是,我导入了 json,http://docs.python.org/2/library/json.html 看看这个,也许很有帮助。记得导入json。这将为您在需要时转储和加载数据提供基础。在这种情况下,我将信息转储并加载到一个空字典中。当您想使用空字典时,try and except 方法非常有用。我发现“r+”最有用,因为它会读写文件。

    def dump_data():
        j = json.dumps(file.text, indent=4)
        with open("database.txt", "w") as f:
            f.write(j)
    
    def load_data():
        try:
            with open("file.txt", "r+") as f:
                return json.load(fp=f)
        except IOError:
                return {}
    

    【讨论】:

    • 现在我正在写入项目以响应交互活动,并在每次写入后将修改刷新到磁盘,因此在严重崩溃或断电的情况下不会丢失任何内容。在此设置中,每次修改后重新写入整个数据感觉相当低效。
    猜你喜欢
    • 1970-01-01
    • 2012-05-06
    • 2015-04-20
    • 1970-01-01
    • 2011-10-02
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多