在大多数当前的 Python 实现中,实际上,一旦文件对象被取消引用,文件就会关闭,因为垃圾收集主要是通过引用计数。
但是,Python 语言 不保证:您依赖于实现细节。
因此,单线将打破当前或未来使用更高级垃圾收集技术(例如将 GC 委托给底层 JVM 或 .Net 运行时)的 Python 实现。
with 确实保证在块退出时立即关闭——在任何正确的语言实现中。因此,它肯定更加健壮和防错。
此外,假设argv[2] 命名的文件存在,但arg[1] 命名的文件不存在。单线:
(open(argv[2], 'w')).write(open(argv[1]).read())
您首先打开要写入的文件(从而清除其内容)——顺便说一句,带有多余的括号,但它们是无害的:-)。 然后在您尝试打开要读取的文件时,遇到异常并失败 - 但您打开的第一个文件无论如何都会不可挽回地消失(即磁盘上留空)。在这种情况下,这不太可能是期望的行为。
在with 变体中,您首先尝试打开要读取的文件——如果失败,您永远不会清除要写入的文件。这对我来说也是一种更强大的行为——这适用于任何版本的 Python,过去、现在或未来:-)。
还有一件事:我想知道规范是否断言文件内容适合内存。如果他们不这样做,尝试一次读取文件将失败并出现内存错误——相反,您需要一个循环读取和写入一些大但有界的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 的文档(以及在同一模块中的copy 和copystat 函数的上方):这可以安全可靠地复制“权限位,最后访问时间,最后修改时间, 和标志”...文件复制还有更多令人印象深刻的内容,shutil 会代您处理所有这些。
学习 Python 标准库至少和学习语言本身一样重要!-)