Python'догу контекст менеджерлери
Даярдоо ар дайым бошотуу менен коштолорун кепилдеңиз, бир нерсе туура эмес кеткенде да
with оператору башкарат: __enter__ кирүүдө иштейт, ал эми __exit__ чыгууда кепилденген түрдө иштейт — блок кадимкидей аяктадыбы, return кездештирдиби же өзгөчө кырдаал (exception) жаратабы, баары бир. Бул тилдин "ресурсту кармоо, аны колдонуу жана сөзсүз бошотуу" маселесине жообу.
withкантип__enter__/__exit__протоколуна чагылдырыларын түшүндүрүү,- класска негизделген ишенимдүү контекст менеджерин жазуу, анын ичинде
__exit__ичинде өзгөчө кырдаалдарды туура иштетүү, - аны
@contextlib.contextmanagerжана генератор менен алда канча арзаныраак түзүү, __exit__кайтарган маани жөнүндө жана ал качан өзгөчө кырдаалдарды жутуп коёору жөнүндө ой жүгүртүү,contextlib.ExitStackаркылуу бир нече менеджерди динамикалык түрдө бириктирүү,- шаблондук коддун ордуна
suppress,closingжанаnullcontextколдонуу.
1. Маселе: өткөрүп жиберүүгө болбогон тазалоо
Дээрлик ар бир олуттуу программа кийин бошотулушу керек болгон ресурстарды кармайт: ачык файлдар, тармак сокеттери, маалымат базасынын байланыштары, агым кулпулары (locks), убактылуу каталогдор. Ашыкча жөнөкөй версия бир нерсе өзгөчө кырдаал жаратаары менен агып кетет (leak):
f = open("data.txt")
process(f.read()) # эгер бул жерде өзгөчө кырдаал болсо, кийинки сап иштебейт
f.close() # АГЫП КЕТҮҮ: файл эч качан жабылбайт
Тарыхый жактан туура чечим — try/finally: finally блогу try блогу кантип аяктаганына карабай иштейт.
f = open("data.txt")
try:
process(f.read())
finally:
f.close() # ДАЙЫМА иштейт, өзгөчө кырдаалда да
Бул иштейт, бирок узун, оңой унутулат, ал эми блок чоңойгон сайын кармоо менен бошотуу бири-биринен алыстайт. Контекст менеджери так ушул try/finally тартибин кайра колдонула турган объектке таңгактайт, ошондо чакырган код бир таза сап жазат.