打开已打开的文件不抛出异常
考虑这两个 Python 程序:
script_a.py
:
from datetime import datetime
from time import sleep
while True:
sleep(1)
with open('foo.txt', 'w') as f:
sleep(3)
s = str(datetime.now())
f.write(s)
sleep(3)
script_b.py
:
while True:
with open('foo.txt') as f:
s = f.read()
print s
先运行 script_a.py
。在它运行的时候,再启动 script_b.py
。这两个程序都能正常运行,但如果 script_a.py
正在打开一个文件,script_b.py
输出的内容会是空的。
我本以为会出现一个 IOError
错误,告诉我这个文件已经被打开了,但实际上并没有出现这个错误,反而文件看起来是空的。这是为什么呢?如果我想检查这个文件是否被其他程序打开,应该怎么做?是简单地检查返回的是否是空字符串,然后再试一次,直到读到其他内容,这样可以吗?还是说有更好的 Python 方法呢?
2 个回答
你可以随便打开一个文件多少次,只要操作系统不阻止你。这在一些复杂操作中,可以让你在一个文件里同时使用多个光标,挺有用的。
至于为什么 script_b.py
觉得文件是空的,原因就是这个文件确实是空的:
with open('foo.txt', 'w') as f:
当你用 w
模式打开一个文件时,它会立刻把文件里的内容清空(也就是截断文件)。在 script_a
运行的前面三秒钟里,文件完全是空的,这就是 script_b
看到的情况。
在你调用 f.write
后的下一个三秒钟里,文件可能还是... 也许是空的。这是因为有个叫做缓冲的东西——文件在磁盘上的内容并不能保证包含你用 write
写入的所有内容,直到你要么 close
(也就是退出上下文管理器的代码块),要么手动调用 flush
来刷新文件句柄。
另外,你也可以选择无缓冲模式,这样写入的内容会立即写入磁盘。
with open('foo.txt','w',0) as f:
#no buffering, f.write() writes immediately to disk
请查看其他答案和评论,了解在Python中如何处理多个文件打开的情况。如果你已经看过这些内容,仍然想在POSIX平台上锁定文件访问,那么你可以使用fcntl库。
要记住以下几点:A) 其他程序可能会忽略你对文件的锁定,B) 一些网络文件系统的锁定功能可能不好,甚至根本没有实现,C) 一定要小心释放锁,避免死锁,因为flock不会检测到这一点[1][2]。
示例....
script_a.py
from datetime import datetime
from time import sleep
import fcntl
while True:
sleep(1)
with open('foo.txt', 'w') as f:
s = str(datetime.now())
print datetime.now(), "Waiting for lock"
fcntl.flock(f, fcntl.LOCK_EX)
print datetime.now(), "Lock clear, writing"
sleep(3)
f.write(s)
print datetime.now(), "releasing lock"
fcntl.flock(f, fcntl.LOCK_UN)
script_b.py
import fcntl
from datetime import datetime
while True:
with open('foo.txt') as f:
print datetime.now(), "Getting lock"
fcntl.flock(f, fcntl.LOCK_EX)
print datetime.now(), "Got lock, reading file"
s = f.read()
print datetime.now(), "Read file, releasing lock"
fcntl.flock(f, fcntl.LOCK_UN)
print s
希望这对你有帮助!