Подтвердить что ты не робот

Безопасно ли открывать файл несколько раз в 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'

Насколько безопасно это поведение? Мне сложно найти источник, говорящий, что все в порядке, и это очень помогло бы, если бы я мог зависеть от этого.

Я не вижу позицию как атрибут файлового объекта, иначе я был бы уверен в этом. Я знаю, что он может храниться внутри итератора, но idk, как .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']

UPDATE
На странице 161 Основная ссылка Python содержит

Тот же файл можно открыть несколько раз в одной программе (или в разные программы). Каждый экземпляр открытого файла имеет свои собственные который может управляться независимо.

Таким образом, похоже, что это действительно безопасное, определенное поведение

4b9b3361

Ответ 1

В современной ОС (после 1969 года для UNIX-подобных ОС или после 2000 года для Windows и, вероятно, до этого, но я считаю Win2K первой "современной" Windows), каждый экземпляр открытого файла ( файловый дескриптор) имеет свой собственный указатель поиска. В классе Python file нет волшебства, что приведет к тому, что экземпляры будут совместно использовать состояние; file является оболочкой для обычного дескриптора файла C, который сам инкапсулирует дескриптор файла ОС, а реализация file.tell() и file.seek() вызывает соответствующие функции C stdio. (Для беспорядочных деталей см. CPython fileobject.c.) Могут быть различия между поведением библиотеки C и базовым поведением ОС, но в этом конкретном случай, который не является фактором.

Если вы используете IronPython или Jython, он будет использовать стандартный .Net или Java файл для своей базовой реализации, который, в свою очередь, будет использовать стандартную библиотеку C или реализацию ОС.

Итак, ваш подход прекрасен, если вы каким-то образом не запускаете Python на некоторых нестандартных ОС с причудливым поведением ввода-вывода.

Вы можете получить неожиданные результаты при написании, если вы не заправляетесь своевременно; данные могут выходить в памяти в течение некоторого времени, прежде чем он на самом деле попадет на диск и будет доступен для других дескрипторов файлов, которые вы открыли в том же файле. Как следует из абзаца в комментарии, эта проблема в любом случае, за исключением очень простых случаев.