Видалити курсор, який використовується в SearchCursor в межах розуміння словника?


12

Якщо найкраще відкривати курсори, використовуючи оператор з переконанням, що його видалено, наприклад:

with arcpy.da.UpdateCursor(fc,fields) as cursor:

Потім, якщо курсор використовується як ітерабельний у розумінні, як це:

d = {k:v for (k,v) in arcpy.da.SearchCursor(fc,fields)}

Чи потрібно видалити курсор після використання його в розумінні?


1
Чудове запитання. Ви намагаєтеся обробити блоки блоків? Є кілька ранніх (в основному застарілих) публікацій на подібну тему, хоча я не можу знайти остаточного джерела щодо нових daкурсорів: sgillies.net/2011/02/01/get-with-it.html та help.arcgis.com/ en / arcgisdesktop / 10.0 / help / index.html # //… . Зокрема, подивіться коментарі @JasonScheirer внизу першого посилання.
Аарон

Відповіді:


13

Чи це абсолютно необхідно - це неправильне запитання. Питання в тому, чи це гарна ідея.

Як правило, в програмуванні вам слід уникати дивних речей і використовувати найкращий інструмент для роботи . Якщо щось має явний спосіб звільнення ресурсів, просто зробіть випуск явним і виконайте це:

with arcpy.da.UpdateCursor(fc,fields) as cursor:
    d = {k: v for (k,v) in cursor}

Чого ви, можливо, не знаєте, це те, що withстаття фактично посилається на додаткову логіку. Запит withвимагає менеджера контексту, який повинен мати метод __enter__(викликається під час введення блоку) та __exit__(викликається, коли блок виходить). Зокрема, __exit__метод викликається незалежно від того, стався виняток, забезпечуючи, що програма завжди звільняє ресурс навіть при помилці. Це дає вашому коду чітку документацію про те, коли ресурс придбаний і коли він випущений, і це гарантує, що ресурс може бути виданий якнайшвидше.

Навпаки, ви не можете насправді залежати від часу виконання, щоб магічно закрити його негайно. Це тому, що спосіб його закриття - це виклик деструктора об'єкта, що може відбутися або не відбутися негайно. Python не дає жодних гарантій щодо того, коли викликається деструктор, лише що це буде врешті-решт, коли об’єкт збирається сміттям. (Див. Тут .) Наразі Python реалізований так, що це відбувається, як тільки немає більше посилання на об'єкт. Але легко випадково поширити посилання на об’єкт, і час виконання Python може змінитися.

Також врахуйте довгострокове обслуговування. Там немає довгострокової посилання на нього зараз, але то , що відбувається в протягом 6 місяців , коли вам потрібно змінити код таким чином, що це посилання? Що робити, якщо це робить хтось інший? Людина, яка вносить зміни, може не думати перейти до withблоку, оскільки там ще не існує жодного. Зробіть прибирання своїх ресурсів звичкою , і у вас з цим буде набагато менше проблем.

Ви дійсно хочете прив’язати свій код до деталей щодо реалізації сміття? Чи хочете ви постійно думати про те, чи можете ви випадково поширювати посилання через виняток? Ні, ви цього не робите. Уявіть, якби це сталося, коли сценарій викликався в ArcMap. Користувач буде змушений закрити весь процес лише для того, щоб випустити файл. Тому не ставте себе в такому положенні. Відпустіть ресурс прямо. Збереження одного рядка коду не варто ризикувати проблемами, які він може спричинити. Контекстні менеджери - це стандартний механізм отримання та випуску ресурсів у Python, і вони роблять це дуже добре.

Суть полягає в тому, що не випускати його явно - це погана ідея.

Це, звичайно, передбачає, що код має певну можливість вплинути на когось іншого, наприклад, ввести його в сценарій, що комусь іншому потрібно буде запустити або підтримувати, або це може затримати доставку вашої роботи, якщо вам доведеться закрити ArcMap повністю, тому що ви не вдається зберегти ваші зміни. Якщо ви єдиний, кого буде впливати проблема, то будь-якими способами летіть перед доброю практикою все, що вам завгодно.


3

Ні, видаляти а cursorпісля використання в розумінні не потрібно. A cursor- це екземпляр класу, який є об'єктом (все в python - це об'єкт). Кожен сеанс python має a, namespaceякий містить посилання на всі об'єкти сеансу - думайте про це як про словник, де ключі є посиланнями на кожен об’єкт, а значення - самі об'єкти. Коли 'число відліку' - кількість клавіш, які посилаються на цей об'єкт, падає до нуля, об'єкт видаляється і пам'ять перерозподіляється . Коли ви використовуєте a cursorдля розуміння, у просторі імен немає посилання на цей об'єкт. Після завершення розуміння об'єкт буде видалено.

У просторі імен немає запису, а тому нічого не потрібно видаляти. ESRI також ілюструє цей синтаксис у прикладі 2, тут .

Для подальшого уточнення, якщо ви запустите:

>>> import arcpy
>>> f = r'C:\Workspace\study_area.shp'
>>> a = arcpy.da.SearchCursor(f, ['*'])

Ви побачите, що в каталозі з'явиться файл .lock (перевірте провідник файлів). Посилання на курсор є a, що змусить cursor(і, отже, блокування) зберігатись, поки не aбуде видалено. Отже, коли ви запустите:

>>> del(a)

Запис у просторі імен буде видалено, а замок буде звільнений (.lock файл зникне). Якщо ви запускаєте:

>>> t = [i for i in arcpy.da.SearchCursor(f, ['*'])]

Ви або не побачите файл блокування, або він зникне після завершення команди. Без запису в просторі імен параметр cursorне є стійким. tвідноситься до списку, який ви тільки що створили, а не cursorдо його створення.

Підводячи підсумок, про видалення потрібно хвилюватися лише cursorsтоді, коли вони мають посилання в просторі імен (тобто, коли ви призначили їм змінну, як aу наведеному вище прикладі).


2
Це надзвичайно погана практика програмування. Якщо щось має явний спосіб звільнення ресурсів, ви використовуєте його .
jpmc26

@ jpmc26, яка частина "надзвичайно погана практика програмування"? Поняття взагалі? Або лише в тому випадку, якщо ітерабельний примірник в межах розуміння? Я подумав, що одним із сильних аргументів для останнього є те, що він негайно звільняє ресурс.
Том

@Tom Не випускає явно ресурси. Зрозуміння - це фантастичний інструмент, а встановлення нормальних ітерабелей всередині них є цілком нормальним. Тут погано те, що об’єкти курсору набувають блокування файлів і немає явного їх випуску. Дивіться мою відповідь для більш детальної інформації.
jpmc26

2

Курсори оновлення та вставки не можуть бути створені для таблиці або класу функцій, якщо для цього набору даних існує ексклюзивний замок. Функції UpdateCursor або InsertCursor виходять з ладу через виключне блокування набору даних. Якщо ці функції успішно створюють курсор, вони застосовують ексклюзивний замок на наборі даних, щоб два сценарії не могли створити оновлення або вставити курсор в один і той же набір даних.

У Python блокування зберігається, поки курсор не відпустить. В іншому випадку всі інші програми або сценарії можуть бути зайвим чином унеможливлено доступ до набору даних. Курсор може випустити одним із наступних:

Включення курсору всередині з оператором, який гарантуватиме звільнення замків незалежно від того, успішно завершено чи ні;

Виклик скидання () на курсор;

Заповнення курсору;

Явне видалення курсору за допомогою оператора del Python - ESRI

Блокування за допомогою курсорів arcpy.da майже аналогічно блокуванню з оригінальними arcpy курсорами.

Після тестування вашого коду, як зазначав gberard, після закінчення розуміння немає посилання на курсор.
Крім того, в класі функцій немає замків після закінчення розуміння.


1
Видалити що? Після закінчення розуміння немає посилання на об'єкт курсору, тому теоретично його слід закрити. Чи реалізація ESRI поводиться так, як ви очікували - це інше питання, і я не думаю, що документи дійсно відповідають на це.
mikewatt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.