使用文件的适当方式?
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 的文档(以及同一模块中 copy
和 copystat
函数的上方):这安全可靠地复制了 "permission bits, last access time, last modification time, and flags"...还有更多引人注目的文件复制,shutil
会代您处理这一切。
学习 Python 标准库至少与学习语言本身一样重要!-)
我正在读 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 的文档(以及同一模块中 copy
和 copystat
函数的上方):这安全可靠地复制了 "permission bits, last access time, last modification time, and flags"...还有更多引人注目的文件复制,shutil
会代您处理这一切。
学习 Python 标准库至少与学习语言本身一样重要!-)