在Python中多次同时打开一个文件安全吗?
我记得在一些低级语言中,如果在一个程序里多次打开同一个文件,可能会导致一个共享的指针位置。不过我在玩Python的时候,似乎没有遇到这个问题:
$ cat file.txt
first line!
second
third
fourth
and fifth
>>> f1 = open('file.txt')
>>> f2 = open('file.txt')
>>> f1.readline()
'first line!\n'
>>> f2.read()
'first line!\nsecond\nthird\nfourth\nand fifth\n'
>>> f1.readline()
'second\n'
>>> f2.read()
''
>>> f2.seek(0)
>>> f1.readline()
'third\n'
这种行为是安全的吗?我找不到相关的资料说这样做没问题,如果能确认这一点,对我来说会很有帮助。
我没有看到文件对象有位置这个属性,否则我会更有信心。虽然我知道位置可能是保存在迭代器内部,但我不太清楚在这种情况下,.tell()是怎么获取到这个位置的。
>>> dir(f1)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__str__', 'close', 'closed', 'encoding', 'fileno', 'flush',
'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline',
'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines',
'xreadlines']
更新
在《Python基础参考》的第161页上提到:
同一个文件可以在同一个程序中(或者不同的程序中)多次打开。每次打开的文件都有自己的文件指针,可以独立操作。
所以看来这确实是安全的,行为是有定义的。
1 个回答
在现代操作系统中(比如1969年后的类UNIX系统,或者2000年后的Windows,虽然在那之前也有现代化的Windows,但我把Win2K算作第一个“现代”Windows),每个打开的文件实例(也叫文件描述符)都有自己的读取位置指针。Python的file
类并没有什么神奇之处,它只是一个普通C语言文件句柄的包装,这个句柄本身又封装了操作系统的文件描述符,而file.tell()
和file.seek()
的实现实际上是调用了相应的C语言标准输入输出函数。(如果想了解更详细的内容,可以查看CPython的fileobject.c
。)C语言库的行为和底层操作系统的行为可能会有差异,但在这个特定的情况下,这并不是问题。
如果你使用的是IronPython或Jython,它们会使用标准的.Net或Java文件对象作为底层实现,而这些又会使用标准的C语言库或操作系统实现。
所以你的做法是没问题的,除非你在某个非标准的操作系统上运行Python,而这个操作系统的输入输出行为很奇怪。
如果你在写入数据时没有及时刷新,可能会得到意想不到的结果;数据可能会在内存中停留一段时间,才会真正写入磁盘,并且对你在同一个文件上打开的其他文件描述符可用。正如abarnert在评论中指出的,这种情况本身就有问题,除非是非常简单的情况。