使用文件的适当方式?

Appropriate way to working with files?

我正在读 Zed Shaw 关于 Python 的书。

有一个练习要求以最少的行数实现从一个文件到另一个文件的复制。我是一行完成的,这里是:

 (open(argv[2], 'w')).write(open(argv[1]).read())

我的问题是,如果我这样做会发生什么最糟糕的事情?我的意思是不关闭它们。

我用另一种方式做了同样的事情,教程说这是更可靠的方法。你怎么看?

with open(argv[1], 'r') as source:
   with open(argv[2], 'w') as dest:
       dest.write(source.read())

我是新人,这种问题可能看起来很傻,但对我来说很重要

感谢您的关注。尼克

在 Python 的大多数当前实现中,实际上,一旦文件对象被取消引用,文件就会关闭,因为垃圾收集主要是通过引用计数。

但是,Python 语言 不能保证:您依赖于实现细节。

因此,单行代码将在当前或未来使用更高级垃圾收集技术(例如,将 GC 委托给底层 JVM 或 .Net 运行时)的实施中中断。

with 确实 保证一旦块退出就关闭——在语言的任何正确实现中。因此,它绝对更加健壮和防错。

另外,假设argv[2]命名的文件存在,但arg[1]命名的文件不存在。在一行中:

(open(argv[2], 'w')).write(open(argv[1]).read())

首先打开要写入的文件(从而清除其内容)——顺便说一句,括号是多余的,但它们是无害的:-)。 Then 在您尝试打开要读取的文件时遇到异常并失败——但是您打开的第一个文件无论如何都无法挽回地被删除(即在磁盘上留空).在这种情况下,这不太可能是所需的行为。

with 变体中,您 首先 尝试打开要读取的文件——如果失败,您永远不会擦除要写入的文件。这对我来说也是更稳健的行为——这适用于 Python 的任何版本,过去、现在或未来:-)。

还有一件事:我想知道规范是否断言文件内容适合内存。如果他们不这样做,尝试在一个 gulp 中读取文件将失败并出现内存错误——相反,您希望一次循环读取和写入一些大但有界的 BUFFER_SIZE 字节.这强调了出于复制目的,最好以二进制而不是文本模式打开文件(文本模式是默认模式,因此在您的代码中使用它,因为您没有另外指定)。就此而言,更稳健的是:

with open(argv[1], 'rb') as source:
    with open(argv[2], 'wb') as dest:
        while True:
            buf = source.read(BUFFER_SIZE)
            if not buf: breal
            dest.write(buf)

有趣的是,仅仅复制一个文件就有多少小细节会出错,嗯?-) 这就是为什么 Python 幸福的关键是学习 Python 的大 标准库,充满了精心编码的模块,以处理即使在最简单的任务中也可能出现的所有各种极端情况。

这个问题的真正答案(如果我面试一位声称精通 Python 的求职者,我会给 A+ 的答案)是(击鼓...):

import shutil

shutil.copy2(argv[1], argv[2])

!-) 请参阅 https://docs.python.org/2/library/shutil.html#shutil.copy2 的文档(以及同一模块中 copycopystat 函数的上方):这安全可靠地复制了 "permission bits, last access time, last modification time, and flags"...还有更多引人注目的文件复制,shutil 会代您处理这一切。

学习 Python 标准库至少与学习语言本身一样重要!-)