生成器中未受保护的 next¶
ID: py/unguarded-next-in-generator
Kind: problem
Security severity:
Severity: warning
Precision: very-high
Tags:
- maintainability
- portability
Query suites:
- python-security-and-quality.qls
函数 next()
如果底层迭代器耗尽,将引发 StopIteration
异常。通常情况下,这没有问题,但在生成器中可能会导致问题。由于 StopIteration
是一个异常,因此它将从生成器中传播出去,导致生成器终止。这不太可能是预期行为,并且可能会掩盖错误。
此问题被认为足够严重,以至于已接受 PEP 479 来修改对生成器中 StopIteration
的处理。因此,不能正确处理 StopIteration
的代码在 Python 的未来版本中可能会失败。
建议¶
对 next()
的每次调用都应该用 try-except
包裹,以显式地处理 StopIteration
异常。
示例¶
在以下示例中,迭代过程中的空文件将静默地截断输出,因为 StopIteration
异常将传播到顶层。
test_files = [
["header1", "text10", "text11", "text12"],
["header2", "text20", "text21", "text22"],
[],
["header4", "text40", "text41", "text42"],
]
def separate_headers(files):
for file in files:
lines = iter(file)
header = next(lines) # Will raise StopIteration if lines is exhausted
body = [ l for l in lines ]
yield header, body
def process_files(files):
for header, body in separate_headers(files):
print(format_page(header, body))
在以下示例中,显式地处理了 StopIteration
异常,从而允许处理所有文件。
def separate_headers(files):
for file in files:
lines = iter(file)
try:
header = next(lines) # Will raise StopIteration if lines is exhausted
except StopIteration:
#Empty file -- Just ignore
continue
body = [ l for l in lines ]
yield header, body
参考资料¶
Python PEP 索引:PEP 479。