Python 使用文件的适当方式?

Python 使用文件的适当方式?,python,python-2.7,Python,Python 2.7,我正在读Zed Shaw关于Python的书 有一个练习要求以最少的行数实现从一个文件到另一个文件的复制。我只用一行就完成了,这是: (open(argv[2], 'w')).write(open(argv[1]).read()) 我的问题是,如果我这样做,会发生什么最糟糕的事情?我的意思是不关闭它们 我用另一种方法做了同样的事情,教程说这是一种更健壮的方法。你觉得怎么样 with open(argv[1], 'r') as source: with open(argv[2], 'w'

我正在读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运行时)的Python实现

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

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

(open(argv[2], 'w')).write(open(argv[1]).read())
首先打开要写入的文件(从而清除其内容)--附带多余的括号,但它们是无害的:-)然后在您尝试打开要读取的文件时,出现异常,但失败了--但是您打开的第一个文件无论如何都无法恢复地被删除(即,磁盘上留有空白)。在这种情况下,这不太可能是理想的行为

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

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

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 bliss的关键是学习Python的大型标准库,其中充满了精心编码的模块,以处理即使在最简单的任务中也可能出现的各种各样的小问题

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

!-)请参阅位于的文档(以及位于同一模块中的
copy
copystat
功能的正上方):这将安全可靠地复制“权限位、上次访问时间、上次修改时间、标志”。。。文件复制还有很多吸引人的地方,
shutil
会代表您处理这些事情


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

我想如果你关心的只是阅读,那么如果你不关闭,就不会有什么不好的事情发生,因为在你结束解释器后,它无论如何都会关闭。如果您对编写感兴趣,那么不关闭可能不好。例如,PyPy不会在取消引用时自动关闭文件,因为它对所有内容都使用垃圾收集。我在一个非常流行的库上提交了一个bug,它在PyPy上崩溃了,因为它在一个紧密的循环中打开了(…).read(),并且耗尽了文件描述符@Eevee,很好的观点:PyPy确实是一个重要的实现(IronPython/Python.Net和Jython也是如此,因为它们都有自己的优势),它们的一个共同点是,它们使用的GC方法比CPython的旧引用计数主体更好。GC是关于恢复内存的,人们不应该指望它来获得其他资源,比如文件描述符!因此,
with
对于保证所有类型资源的最终确定(FD最常见,但DB连接、锁和无数其他资源也在上面!)的重要性是非常好的,并且详尽的解释。谢谢
import shutil

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