Объяснение для одной операции чтения на поведение оператора open ()? - PullRequest
1 голос
/ 20 января 2020

Недавно я столкнулся со странным поведением оператора with open () в Python. Следующий код возвращает выходные данные только для первого оператора чтения с пустым списком строк.

input_csv = []
with open(self.path, 'r') as f:  # Opening the CSV
    r = csv.DictReader(f)
    for row in r:
        input_csv.append(row)  # Storing its contents in a dictionary for later use
    lines = f.readlines()  # Reading it in as a list too
    f.close()

При разбиении его на два оператора open () объекты возвращаются по желанию.

input_csv = []
with open(self.path, 'r') as f:  # Opening the CSV
    r = csv.DictReader(f)
    for row in r:
        input_csv.append(row)  # Storing its contents in a dictionary for later use
    f.close()

with open(self.path, 'r') as f:  # Opening the CSV
    lines = f.readlines()  # Reading it in as a list too
    f.close()

Почему переменная f используется только один раз в первом операторе?

Большое спасибо

1 Ответ

0 голосов
/ 20 января 2020

Если вы посмотрите документацию csv.reader(), которая используется для DictReader().reader:

Вернуть объект чтения, который будет повторяться по строкам в данном csvfile . csvfile может быть любым объектом, который поддерживает протокол итератора и возвращает строку каждый раз, когда вызывается его метод __next__() ...

Следовательно, он использует поведение, подобное файлу объект, для которого каждая итерация по существу равна f.readline(). Операция, которая также увеличивает текущую позицию в файле ... до достижения EOF, что при итерации вызывает исключение StopIteration. Это то же поведение, которое вы наблюдаете, пытаясь:

with open(self.path, 'r') as f:
    for l in f:
        pass  # each line was read
    print(f.readlines())

Вы можете добавить print(f.tell()), чтобы увидеть, как изменяется позиция при выполнении каждой строки.

Если вы (повторно) открываете новый файл, вы начинаете с позиции 0 (снова). Если вы прочитали один раз и хотели снова использовать тот же дескриптор, вам нужно вернуться к началу файла: f.seek(0).

Примечание: вам действительно не нужно выполнять f.close() в управляемый контекст с использованием with. Как только вы оставите его, он закроет дескриптор файла для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...