适当的文件处理方式?

Sup*_*ver 2 python python-2.7

我正在阅读Zed Shaw关于Python的书.

有一个练习要求以最少的行数从一个文件到另一个文件实现复制.我在一行中做到了,这是它:

 (open(argv[2], 'w')).write(open(argv[1]).read())
Run Code Online (Sandbox Code Playgroud)

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

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

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

我是新手,这类问题可能看起来很傻,但对我来说很重要.

感谢您的关注.缺口

Ale*_*lli 5

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

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

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

with 尽快退出块封保证-任何正确执行语言.因此,它肯定更强大和防错.

此外,假设文件名为argv[2]exists,但名称为by的文件arg[1]不存在.在单线:

(open(argv[2], 'w')).write(open(argv[1]).read())
Run Code Online (Sandbox Code Playgroud)

首先打开待写文件(从而消除其内容) - 用冗余括号BTW,但它们是无害的:-). 然后在您尝试打开要读取的文件,获取异常并失败 - 但是您打开的第一个文件无论如何都无法挽救(即,在磁盘上留空).在这种情况下,这不太可能是期望的行为.

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)
Run Code Online (Sandbox Code Playgroud)

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

这个问题的真正答案(我给A +的那个人采访的是一个声称掌握了Python的求职者)是(鼓声......):

import shutil

shutil.copy2(argv[1], argv[2])
Run Code Online (Sandbox Code Playgroud)

! - )请参阅https://docs.python.org/2/library/shutil.html#shutil.copy2上的文档(以及上面的相同模块中的copycopystat函数):这可以安全可靠地复制"权限位" ,最后的访问时间,最后的修改时间标志"...还有更多的文件复制,并shutil代表你完成所有的文件复制.

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