أكثر

مما اضطر أداة بايثون أدوات لكسر حلقة والقيام تنظيف عند إلغاء ينقر المستخدم؟

مما اضطر أداة بايثون أدوات لكسر حلقة والقيام تنظيف عند إلغاء ينقر المستخدم؟


وأنا أكتب أداة بايثون التي تؤدي المهام الثقيلة في حلقة. عندما ينقر المستخدم على "إغلاق" ، أريد كسر الحلقة ، وإجراء بعض التنظيف ، ثم الانتهاء.

ضع في اعتبارك أداة المثال التي تعد تنازليًا من عشرة:

import arcpy import time class Tool (كائن): def __init __ (self): self.label = "Cancel Test" self.description = "تختبر كيفية عمل وظيفة الإلغاء." self.canRunInBackground = تنفيذ خطأ خطأ (ذاتي ، معلمات ، رسائل): لـ i في النطاق (10 ، -1 ، -1): arcpy.AddMessage (i) time.sleep (1) arcpy.AddMessage ("لدينا رفع- قبالة! ") العودة

عندما أنقر على "إغلاق" في بداية التنفيذ ، فإنه لا يوقف الحلقة أو يمنحني فرصة لإجراء أي تنظيف. بدلاً من ذلك ، فإنه يتكرر حتى النهاية ويضيف الرسالة"لدينا يقلع!"قبل أن يخرج هذا:

اكتمل البرنامج النصي CancelTest ... تم إحباط الوظيفة الملغاة (CancelTest) من قبل المستخدم. فشل في [TIME] (الوقت المنقضي: 10،01 ثانية)

لقد عثرت على وثائق ArcGIS Pro (التي تستخدم Python 3.4) التي توضح كيفية القيام بذلك هناك باستخدامتم إلغاء:

استيراد وقت استيراد arcpy #Make تأكد من أنها لا تلغي السيارات. arcpy.env.autoCancelling = False class Tool (object): def __init __ (self): self.label = "Cancel Test" self.description = "اختبار كيفية عمل وظيفة الإلغاء." self.canRunInBackground = تنفيذ خطأ خطأ (ذاتي ، معلمات ، رسائل): بالنسبة لـ i في النطاق (10 ، -1 ، -1): arcpy.AddMessage (i) time.sleep (1) #Check إذا قام المستخدم بالنقر فوق "إغلاق" إذا كان arcpy.env.isCancelled: arcpy.AddMessage ("تم إحباط الإطلاق!") قم بإرجاع arcpy.AddMessage ("لدينا إقلاع!")

ومع ذلك ، عند تشغيل هذا من ArcCatalog 10.3 (أي عدم استخدام ArcGIS Pro) فإنه يعطيني الخطأ التالي:

Traceback (المكالمات الأخيرة الأخيرة): ملف "H:  مينا Dokument  DGD  بيثون  CancelTest.py"، خط 19، في تنفيذ إذا arcpy.env.isCancelled: AttributeError: الكائن 'GPEnvironment "لا يوجد لديه السمة' isCancelled"

هل هناك أي طريقة لتقليد السلوك المتاح في ArcGIS Pro في مربع أدوات Python العادي باستخدام Python 2.7؟


إجابة فريد شير صحيحة جزئيًا.

يمكنك استخدام Progressor لـ "التقاط" حدث إلغاء من داخل نص برمجي Python ، ويمكنك أيضًا إجراء أي تنظيف ضروري أيضًا ، إذا قمت بإرفاق المكالمة داخلحاول… ما عدابند.

على سبيل المثال ، صندوق أدوات Python:

import arcpy import time class Toolbox (object): def __init __ (self): self.label = "Toolbox" self.alias = "" self.tools = [أداة] class Tool (object): def __init __ (self): self. label = "Tool" self.description = "" self.canRunInBackground = تنفيذ خطأ خطأ (ذاتي ، معلمات ، رسائل): some_stuff = [] # متغير للتنظيف لاحقًا max = 1000 arcpy.SetProgressor ('step'، 'Testing ArcPy script Cancel '، 0، max، 1) # ليس عليك أن تكون في حلقة for ، ولكن هذه هي الطريقة الأسهل # لإظهار مثال لـ i في النطاق (max): حاول: # فقط ضع SetProgressorPosition في هذا clause # وإلا يمكنك اكتشاف الأخطاء الأخرى التي لا # يقوم المستخدم بإلغاء arcpy.SetProgressorPosition () باستثناء: arcpy.AddWarning ('تم إلغاء المستخدم في i = {0}'. format (i)) del some_stuff # cleanup return time. sleep (0.1) some_stuff.append (i) arcpy.AddMessage ('لم يُلغِ المستخدم') del some_stuff

هذا يسمح للمستخدم بتشغيل الأداة:

ثم الإلغاء ، الذي يتم التعامل معه بأمان (ولا يزال يُحسب على أنه تشغيل فاشل):

تعديل: يبدو أن هذا لا يعمل مع الإصدار 10.3 أو ArcGIS Pro.

للقبض على الإلغاءات (التي تم اختبارها في ArcGIS Pro) ، نعيد صديقنا العزيزالقوس. هذا مشابه لالتقاط الإلغاء من التطور ، لكن وظيفة التنفيذ بأكملها ، أو على الأقل الغالبية منها ، يجب أن تكون داخليحاول:

استيراد arcpy import arcgisscripting import time class Toolbox (object): def __init __ (self): self.label = "Toolbox" self.alias = "" self.tools = [الأداة] class Tool (object): def __init __ (self): self.label = "Tool" self.description = "" self.canRunInBackground = تنفيذ خطأ خطأ (self ، معلمات ، رسائل): جرب: some_stuff = [] max = 1000 arcpy.SetProgressor ('step'، 'Testing ArcPy script إلغاء '، 0، الحد الأقصى، 1) لأنني في مجموعة (كحد أقصى): arcpy.SetProgressorPosition () time.sleep (0.1) some_stuff.append (ط) باستثناء arcgisscripting.ExecuteAbort: arcpy.AddWarning (' إلغاء في الاول العضو = {0 } '. format (i)) del some_stuff return arcpy.AddMessage (' User didn't Cancel ') del some_stuff


رسالتك واضحة:

خطأ Attribute: لا يحتوي كائن 'GPEnvironment' على سمة 'isCancelled'

في الحقيقةarcpy.env.autoCancellingوarcpy.env.is تم إلغاؤهاتمت إضافتها في Arcgis Pro 1.1 (مخطط لـ ArcGIS 10.4)

علاوة على ذلك ، إذا كنت تستخدم Arcgis 10.3 ، فلن تكون هذه الميزات متاحة.


أقرب طريقة يمكنني التفكير بها هي استخدام Progressor في Arcpy. باستخدام التطور ، بمجرد أن يضغط المستخدم على زر الإلغاء ، تنكسر الحلقة وينتهي التنفيذ. ومع ذلك لا يمكنك القيام بأي تنظيف! إليك نموذج التعليمات البرمجية:

def execute (self ، parameters ، messages): import time n = 10 p = 1 arcpy.SetProgressor ("step"، "Step progressor: Counting from 0 to {0}". format (n)، 0، n، p) loopTime = .3 لـ i في النطاق (n): إذا (i٪ p) == 0: ## ضع الكود المخصص هنا ## فسوف يكسر الحلقة إذا ألغى المستخدم. وأداة التنفيذ إنهاء arcpy.SetProgressorLabel ( "التكرار: {0}". شكل (ط)) arcpy.SetProgressorPosition (ط) time.sleep (loopTime) arcpy.AddMessage ( "أنت لن تحصل هنا للقيام تنظيف إذا كانت الحلقة إنهاء قبل الأوان ") arcpy.SetProgressorLabel (" تم الانتهاء من التكرار: {0} ". تنسيق (i + 1)) إرجاع arcpy.SetProgressorPosition (i + 1)

تحديث (للإجابة على الأسئلة في التعليق):

لماذا يغير استخدام مُطور التطور كيفية تصرف البرنامج ، بخلاف إضافة شريط تقدم جميل المظهر؟

المُطور هو نوع من المعالجة متعددة الخيوط. في كل مرة يتقدم فيها المُطور للأمام ، يجب تحديث واجهة المستخدم الرسومية (سلسلة منفصلة). أثناء استخدام progressor، تقوم بتشغيل التعليمات البرمجية في موضوع المضمنة آخر. ومع ذلك فإنه ليس بالتأكيد مثل الخلفية الجغرافية معالجة حيث يمكنك تشغيل موضوع متعددة في وقت واحد.

هل استخدام التطور يجعل ArcGIS يوقف الكود عندما يضغط المستخدم على "إلغاء"؟

نعم ، لاحظ أن القطع يحدث في الحلقة ، حيث تقوم بتحديث شريط التقدم الخاص بك (على سبيل المثال ، مثل المثال أعلاه)

اين تنكسر؟ هل هي مباشرة بعد أي سطر يحدث عند الضغط على الزر؟

يحدث الاختراق بين أي خطوتين للتقدم يقوم المستخدم بالنقر فوق الزر "إلغاء". في مثال الكود أعلاه:

إذا (i٪ p) == 0: ## ضع الكود المخصص هنا ## فسوف يكسر الحلقة إذا ألغى المستخدم. وينهي تنفيذ الأداة arcpy.SetProgressorLabel ("التكرار: {0}". تنسيق (i))

إذا نقر المستخدمإلغاء، سيتم تنفيذ التعليمات البرمجية المخصصة الخاصة بك حتى تصلarcpy.SetProgressorLabel ("التكرار: {0}". تنسيق (i)). هذا هو المكان الذي سيتم فيه إخطار أداة gp بحدث الإلغاء (على سبيل المثال ، قتل سلسلة الرسائل المضمنة المنفصلة)


شاهد الفيديو: لغة بايثون شرح الفصل السابع المقطع الثاني