هل هناك طريقة لمنع اكتشاف استثناء SystemExit المرفوع من sys.exit()؟

StackOverflow https://stackoverflow.com/questions/173278

سؤال

تقول المستندات أن استدعاء sys.exit() يثير استثناء SystemExit والذي يمكن اكتشافه في المستويات الخارجية.لدي موقف أرغب فيه في الخروج بشكل نهائي وغير قابل للشك من داخل حالة اختبار، ولكن وحدة Unittest تلتقط SystemExit وتمنع الخروج.يعد هذا أمرًا رائعًا عادةً، ولكن الموقف المحدد الذي أحاول التعامل معه هو الموقف الذي اكتشف فيه إطار الاختبار الخاص بنا أنه تم تكوينه للإشارة إلى قاعدة بيانات غير اختبارية.في هذه الحالة أريد الخروج ومنع إجراء أي اختبارات أخرى.بالطبع بما أن Unittest يحاصر SystemExit ويستمر بسعادة في طريقه، فهو يحبطني.

الخيار الوحيد الذي فكرت فيه حتى الآن هو استخدام ctypes أو شيء مشابه لاستدعاء خروج (3) مباشرة ولكن هذا يبدو وكأنه اختراق قبيح جدًا لشيء يجب أن يكون بسيطًا حقًا.

هل كانت مفيدة؟

المحلول

ويمكنك الاتصال os._exit() للخروج مباشرة، دون طرح استثناء :

import os
os._exit(1)

وهذا يتجاوز كل منطق اغلاق الثعبان، مثل وحدة atexit، وسوف يتم تشغيل من خلال منطق معالجة الاستثناء الذي كنت تحاول تجنب في هذه الحالة. والحجة هي رمز إنهاء التي سيتم إرجاعها من قبل هذه العملية.

نصائح أخرى

وكما قال يروب os._exit(1) هو جوابك.ولكن، مع الأخذ في الاعتبار أنه يتجاوز الجميع إجراءات التنظيف، بما في ذلك finally: الكتل وإغلاق الملفات وما إلى ذلك، ويجب تجنبها بأي ثمن، هل يمكنني تقديم طريقة "أكثر أمانًا" لاستخدامها؟

إذا كنت المشكلة SystemExit الوقوع في المستويات الخارجية (أي، Unittest)، إذن كن المستوى الخارجي بنفسك! قم بلف الكود الرئيسي الخاص بك في كتلة محاولة/باستثناء، ثم التقط SystemExit، ثم اتصل بـ os._exit هناك، و فقط هناك! بهذه الطريقة يمكنك الاتصال sys.exit عادةً في أي مكان في الكود، دعه يخرج إلى المستوى الأعلى، ويغلق جميع الملفات بأمان ويشغل جميع عمليات التنظيف، و ثم استدعاء os._exit.

يمكنك أيضًا اختيار مخارج "الطوارئ".الكود أدناه هو مثال على هذا النهج:

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top