2016-07-14 4 views
2

Я только что видел следующий код:Принимая генератор из менеджера контекста

from __future__ import print_function 
from future_builtins import map # generator 

with open('test.txt', 'r') as f: 
    linegen = map(str.strip, f) 

# file handle should be closed here 

for line in linegen: 
    # using the generator now 
    print(line) 

Что происходит в этом случае? Является ли контекстный менеджер достаточно умным, чтобы знать, что linegen все еще имеет ссылку на дескриптор файла, так что он не закрыт, когда контекст остается? Или это потенциально опасно?

+0

Вы пробовали ? –

+0

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

+1

это просто выглядит неправильно –

ответ

2

Это одна из тех отличиях в Python 3.

Ваш вопрос название (Принимая генератор ...) означает, что вы читаете это, как Python 3 кода.

Но заявление

from __future__ import print_function 

означает, что было написано на Python 2

В Python 2, map возвращает фактический список - и, таким образом, этот код и совершенно безопасен и extrmely разумный (т.е. открыть файл, прочитать все строки, с расцепления их, как вы идете, а затем закройте файл)

In [2]: with open('README.md','r') as f: 
    ...:  lines = map(str.strip, f) 
    ...:  
In [3]: lines 
Out[3]: 
['ASM', 
'============', 
'', 

В Python 3, и тот же код выдает исключение

In [1]: with open('README.md','r') as f: 
    lines = map(str.strip, f) 
    ...:  
In [2]: lines 
Out[2]: <map at 0x7f4d393c3ac8> 
In [3]: list(lines) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-3-2666a44c63b5> in <module>() 
----> 1 list(lines) 

ValueError: I/O operation on closed file. 

Если вы хотите версия безопасной реализации этого вам необходимо либо преобразовать генератор в список

lines = list(map(str.strip, f)) 

или просто использовать список понимание

lines = [l.strip() for l in f] 
+0

'from future_builtins import map' делает' map' генератором также в Python 2. Меня интересовали приоритеты открытого ссылочного или выходящего контекста. Кажется, контекст выигрывает, поскольку каждый постоянно получает исключение. Во что бы то ни стало, не стесняйтесь закрыть вопрос. – Stefan

Смежные вопросы