পাইথনে অপ্রকাশিত ব্যতিক্রমগুলি লগ ইন করা


181

আপনি না করে loggingমডিউলটির মাধ্যমে আউটপুট থেকে কীভাবে ব্যতিক্রম বোধ করবেন stderr?

আমি বুঝতে পারছি এটি করার সর্বোত্তম উপায় হ'ল:

try:
    raise Exception, 'Throwing a boring exception'
except Exception, e:
    logging.exception(e)

তবে আমার পরিস্থিতি এমন যে খুব ভাল লাগবে যদি logging.exception(...)কোনও ব্যতিক্রম ধরা না পড়লে স্বয়ংক্রিয়ভাবে আহ্বান করা হয়।



উত্তর:


143

নেড উল্লেখ করেছেন, sys.excepthookপ্রতিবার একটি ব্যতিক্রম উত্থাপিত হয় এবং তা ছাড়ানো হয় না। এর ব্যবহারিক নিদর্শনটি হ'ল sys.excepthookআপনার কোডটিতে আপনি যা চান তা করার ব্যবহারের ডিফল্ট আচরণকে ওভাররাইড করতে পারেন (ব্যবহার সহ logging.exception)।

খড়ের উদাহরণ হিসাবে:

>>> import sys
>>> def foo(exctype, value, tb):
...     print 'My Error Information'
...     print 'Type:', exctype
...     print 'Value:', value
...     print 'Traceback:', tb
... 

ওভাররাইড sys.excepthook:

>>> sys.excepthook = foo

সুস্পষ্ট বাক্য গঠন ত্রুটি করুন (কোলনটি ছেড়ে দিন) এবং কাস্টম ত্রুটির তথ্য ফিরে পান:

>>> def bar(a, b)
My Error Information
Type: <type 'exceptions.SyntaxError'>
Value: invalid syntax (<stdin>, line 1)
Traceback: None

সম্পর্কে আরও তথ্যের জন্য sys.excepthook: http://docs.python.org/library/sys.html#sys.excepthook


4
@ কোডমনকি এটি কোনও সংরক্ষিত কীওয়ার্ড নয়, এটি একটি প্রিফিক্সিং টাইপের নাম। আপনি typeএকটি ফাংশন যুক্তি হিসাবে ব্যবহার করতে পারেন , যদিও আইডিইগুলি বিশ্বব্যাপী লুকানোর বিষয়ে অভিযোগ করবে type(অনেকটা var self = thisজাভাস্ক্রিপ্টে ব্যবহার করার মতো ) like typeআপনার ফাংশনের অভ্যন্তরে অবজেক্টটি অ্যাক্সেস করার প্রয়োজন না থাকলে এটি আসলেই গুরুত্বপূর্ণ নয়, সেক্ষেত্রে আপনি type_পরিবর্তে যুক্তি হিসাবে ব্যবহার করতে পারেন ।
রায়ান পি

3
এখানে "প্রতিবার " শব্দগুচ্ছটি বিভ্রান্তিকর ::: "sys.excepthook প্রতিবার একটি ব্যতিক্রম উত্থাপিত এবং অপ্রত্যাশিত করা হয়" ... কারণ একটি প্রোগ্রামে ঠিক একটি "অপ্রচলিত" ব্যতিক্রম হতে পারে । এছাড়াও, যখন কোনও ব্যতিক্রম "উত্থাপিত হয়" বলা হয় না। এটি বলা হয় যখন প্রোগ্রামটি একটি অপ্রকাশিত ব্যতিক্রমের কারণে শেষ হতে চলেছে, যা একাধিকবার ঘটতে পারে না। sys.excepthook
নওয়াজ

2
@ নাওয়াজ: এটি একটি রিপল
জেফএস

2
@ নাওয়াজ প্রোগ্রামটি থ্রেড ব্যবহার করে থাকলে এটি একাধিকবার ঘটতেও পারে। আমিও দেখেছি জিআইআই ইভেন্টের লুপগুলি (কিউটিউটের মতো) চলতে থাকবে, যদিও ব্যাতিক্রমটি এটি sys.excepthook এ তৈরি করেছে
three_pineapples

1
যে কোনও ব্যক্তি উপরের কোডটি পরীক্ষা করার চেষ্টা করছেন, নিশ্চিত করুন যে আপনার ফাংশনটি পরীক্ষা করার সময় আপনি কোনও ট্রেসব্যাক ত্রুটি তৈরি করেছেন। সিনট্যাক্স এরির sys.excepthook দ্বারা পরিচালিত হচ্ছে না। আপনি মুদ্রণ (1/0) ব্যবহার করতে পারেন এবং এটি sys.excepthook
পার্থ কারিয়া

177

এখানে একটি সম্পূর্ণ ছোট উদাহরণ যা এর সাথে কয়েকটি অন্যান্য কৌশলও অন্তর্ভুক্ত রয়েছে:

import sys
import logging
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

def handle_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))

sys.excepthook = handle_exception

if __name__ == "__main__":
    raise RuntimeError("Test unhandled")
  • কীবোর্ডটিকে অবহেলা করুন অন্তরায় করুন যাতে একটি কনসোল পাইথন প্রোগ্রামটি Ctrl + C দিয়ে প্রস্থান করতে পারে

  • ব্যতিক্রম ফর্ম্যাট করার জন্য অজগরটির লগিং মডিউলে সম্পূর্ণভাবে নির্ভর করুন।

  • উদাহরণ হ্যান্ডলার সহ একটি কাস্টম লগার ব্যবহার করুন। এটি স্টাডারের পরিবর্তে স্ট্যান্ডআউটে যাওয়ার জন্য অযৌক্তিক ব্যতিক্রম পরিবর্তন করে তবে আপনি একই স্টাইলে সমস্ত ধরণের হ্যান্ডলার লগার অবজেক্টে যুক্ত করতে পারেন।


13
আমি logger.critical()ব্যাতিক্রমী হ্যান্ডলারের ভিতরে ব্যবহার করব , যেহেতু একটি অনাবৃত ব্যতিক্রম বেশ সমালোচিত আমি বলব।
গীতারিক

2
এটি সবচেয়ে ব্যবহারিক উত্তর আইএমও।
ডেভিড মোরালেস

স্নিপেটের জন্য @gnu_lorien ধন্যবাদ আপনি কোন ফাইল এ লাগাতে হবে?
স্টিলিওস

@ শেফারভ প্রধান ফাইল যেখানে আপনি অন্য সমস্ত লগইন শুরু করেন
gnu_lorien

হাই, আমরা কীভাবে এই তথ্যটি ডিবাগ.লগের মতো ফাইল করতে লিখতে পারি। আমি লাইন যুক্ত করার চেষ্টা logging.basicConfig(level=logging.DEBUG, filename="debug.log", format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')করেছিলাম কিন্তু সাহায্য করেনি।
গুরহানকাগিন

26

sys.excepthookকোনও ব্যতিক্রম না ছাড়লে পদ্ধতিটি শুরু করা হবে: http://docs.python.org/library/sys.html#sys.excepthook

যখন কোনও ব্যতিক্রম উত্থাপিত হয় এবং অবহিত না হয়, তখন দোভাষী সেসময়ে.সেসপেক্সটুককে তিনটি যুক্তি, ব্যতিক্রম শ্রেণি, ব্যতিক্রম উদাহরণ এবং একটি ট্রেসব্যাক অবজেক্ট সহ কল ​​করে calls একটি ইন্টারেক্টিভ সেশনে নিয়ন্ত্রণটি প্রম্পটে ফিরে আসার ঠিক আগে ঘটে; পাইথন প্রোগ্রামে প্রোগ্রামটি শেষ হওয়ার ঠিক আগে ঘটে। এই ধরনের শীর্ষ-স্তরের ব্যতিক্রমগুলির হ্যান্ডলিংটিকে সিএস.সেপ্টথবুকে অন্য তিন-যুক্তি ফাংশন বরাদ্দ করে কাস্টমাইজ করা যায়।


2
কেন এটি ব্যতিক্রম ক্লাস পাঠায়? typeউদাহরণস্বরূপ ফোন করে আপনি কি সবসময় পেতে পারেন না ?
নীল জি

23

কেন না:

import sys
import logging
import traceback

def log_except_hook(*exc_info):
    text = "".join(traceback.format_exception(*exc_info))
    logging.error("Unhandled exception: %s", text)

sys.excepthook = log_except_hook

None()

sys.excepthookউপরে প্রদর্শিত হিসাবে আউটপুট এখানে :

$ python tb.py
ERROR:root:Unhandled exception: Traceback (most recent call last):
  File "tb.py", line 11, in <module>
    None()
TypeError: 'NoneType' object is not callable

এখানে sys.excepthookমন্তব্য সহ আউটপুট দেওয়া হয়েছে:

$ python tb.py
Traceback (most recent call last):
  File "tb.py", line 11, in <module>
    None()
TypeError: 'NoneType' object is not callable

পার্থক্যটি হ'ল ERROR:root:Unhandled exception:প্রথম লাইনের শুরুতে প্রাক্তনটির রয়েছে ।


আর একটি পার্থক্য হ'ল প্রাক্তন লগিং সিস্টেমে ট্রেস লেখেন, সুতরাং আপনার ইনস্টল করা যে কোনও হ্যান্ডলার এবং ফর্ম্যাটর প্রয়োগ করা হয়। পরেরটি সরাসরি লিখতে sys.stderr
রেডিয়াফ

8

জ্যাকিন্ডার উত্তরটি তৈরি করতে, তবে লগার অবজেক্টটি ব্যবহার করে:

def catchException(logger, typ, value, traceback):
    logger.critical("My Error Information")
    logger.critical("Type: %s" % typ)
    logger.critical("Value: %s" % value)
    logger.critical("Traceback: %s" % traceback)

# Use a partially applied function
func = lambda typ, value, traceback: catchException(logger, typ, value, traceback)
sys.excepthook = func

2
functools.partial()ল্যাম্বদার পরিবর্তে ব্যবহার করা ভাল । দেখুন: docs.python.org/2/library/functools.html#functools.partial
মারিউজ জামরো

@ মারিয়াসজামরো কেন?
ডেভর

4

আপনার অ্যাপ্লিকেশন এন্ট্রি কলটিকে একটি try...exceptব্লকে মোড়ক করুন যাতে আপনি সমস্ত অজানা ব্যতিক্রমগুলি ধরতে এবং লগ করতে (এবং সম্ভবত পুনরায় উত্থাপন) করতে সক্ষম হবেন। যেমন পরিবর্তে:

if __name__ == '__main__':
    main()

এটা কর:

if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        logger.exception(e)
        raise

এই প্রশ্নটি জিজ্ঞাসা করা হয় না। প্রশ্নের উদ্দেশ্য হ'ল ব্যতিক্রম কোড দ্বারা পরিচালিত না হলে কি করবেন।
মায়াঙ্ক জয়সওয়াল

1
ঠিক আছে, পাইথন একটি প্রোগ্রামিং ভাষা এবং এর থেকে বোঝা যায় যে এটি "স্বয়ংক্রিয়ভাবে" (ওপি যেমন চায়) কিছুই করে না, যদি আপনি কখন এটি করতে বলেন তবে। অন্য কথায়, সমস্ত ব্যতিক্রমগুলি "স্বয়ংক্রিয়ভাবে" লগ করার কোনও উপায় নেই, যদি আপনি এটির জন্য কোড না করেন - এবং এটিই আমার উত্তরে রয়েছে।
ফ্ল্যাভিওভস

1
ঠিক আছে, যদি আপনি নেড ব্যাচেল্ডারের উত্তরটি লক্ষ্য করেন তবে ব্যতিক্রম হুক বলে কিছু আছে। আপনাকে আপনার কোডের এক জায়গায় নির্ধারণ করতে হবে এবং আপনার অবিচ্ছিন্ন সমস্ত ব্যতিক্রমগুলি পরিচালনা করা হবে।
মায়াঙ্ক জয়সওয়াল

1
ব্যতিক্রম হুক এই সত্যটি পরিবর্তন করে না যে এটি "স্বয়ংক্রিয়" নয় (অর্থে ওপি চায়) - অন্য কথায়, আপনাকে এখনও এটি কোড করতে হবে। নেডের উত্তর (যা ব্যতিক্রম হুক ব্যবহার করে) সত্যই আসল প্রশ্নটি সম্বোধন করে - এটি আমার মতে , এটি যেভাবে করে তা আমার চেয়ে পাইথোনিকের চেয়ে অনেক কম।
ফ্ল্যাভিওভস

1
এটি প্রায় আপনার নিজস্ব উদ্দেশ্য উপর নির্ভর করে। আপনি যদি আইডিইকে খুশি করার প্রোগ্রাম করেন তবে হ্যাঁ সমস্ত ব্যতিক্রম ধরা কোনও বিকল্প হতে পারে না। তবে আপনি যদি ত্রুটিগুলি নিখুঁতভাবে পরিচালনা করতে চান এবং ব্যবহারকারীর কাছে দুর্দান্ত প্রতিক্রিয়া প্রদর্শন করতে চান তবে আমি আশঙ্কা করছি যে আপনার সমস্ত ব্যতিক্রম ধরা পড়তে হবে। ঠিক আছে, যথেষ্ট ব্যঙ্গাত্মক :-) - আপনি সাবধানতার সাথে লক্ষ্য করলে আপনি দেখতে পাবেন যে কোডটি ব্যতিক্রমটিকে বিরত রাখে তবে আবার উত্থাপন করুন, সুতরাং আপনার আইডিই কিছু না করে "জাদুকরী" করছেন না, এটি এখনও পাবেন ব্যতিক্রম.
flaviovs

3

হতে পারে আপনি মডিউলটির শীর্ষে এমন কিছু করতে পারেন যা স্টাডারকে একটি ফাইলে পুনঃনির্দেশ করে এবং তারপরে সেই ফাইলটি নীচে লগ করে

sock = open('error.log', 'w')               
sys.stderr = sock

doSomething() #makes errors and they will log to error.log

logging.exception(open('error.log', 'r').read() )

3

যদিও @ gnu_lorien এর উত্তর আমাকে ভাল সূচনা পয়েন্ট দিয়েছে, আমার প্রোগ্রামটি প্রথম ব্যতিক্রমেই ক্র্যাশ হয়ে গেছে।

আমি একটি কাস্টমাইজড (এবং / অথবা) উন্নত সমাধান নিয়ে এসেছি, যা সজ্জায় সজ্জিত ফাংশনগুলির ব্যতিক্রমগুলি নীরবে লগ করে @handle_error

import logging

__author__ = 'ahmed'
logging.basicConfig(filename='error.log', level=logging.DEBUG)


def handle_exception(exc_type, exc_value, exc_traceback):
    import sys
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    logging.critical(exc_value.message, exc_info=(exc_type, exc_value, exc_traceback))


def handle_error(func):
    import sys

    def __inner(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception, e:
            exc_type, exc_value, exc_tb = sys.exc_info()
            handle_exception(exc_type, exc_value, exc_tb)
        finally:
            print(e.message)
    return __inner


@handle_error
def main():
    raise RuntimeError("RuntimeError")


if __name__ == "__main__":
    for _ in xrange(1, 20):
        main()

2

গৃহীত উত্তরের মন্তব্য বিভাগে আলোচিত মিঃ জিউসের প্রশ্নের উত্তর দেওয়ার জন্য, আমি এটি একটি ইন্টারেক্টিভ কনসোলে (পাইচার্ম 2018-2019 এর সাথে পরীক্ষিত) অবিচ্ছিন্ন ব্যতিক্রমগুলি লগ করতে ব্যবহার করি। আমি খুঁজে sys.excepthookপেয়েছি যে পাইথন শেলটিতে কাজ করে না তাই আমি আরও গভীর করে দেখতে পেলাম যে এর sys.exc_infoপরিবর্তে আমি ব্যবহার করতে পারি । যাইহোক, 3 টি আর্গুমেন্ট লাগে তার sys.exc_infoবিপরীতে কোন আর্গুমেন্ট লাগে না sys.excepthook

এখানে, আমি উভয় ব্যবহার sys.excepthookএবং sys.exc_infoএকটি লেফাফা ফাংশন একটি ইন্টারেক্টিভ কনসোলে উভয় ব্যতিক্রম এবং একটি স্ক্রিপ্ট লগইন করুন। উভয় ফাংশনের সাথে একটি হুক ফাংশন সংযুক্ত করতে, আমার দুটি ভিন্ন ইন্টারফেস রয়েছে যদি যুক্তি দেওয়া হয় বা না হয় তার উপর নির্ভর করে।

কোডটি এখানে:

def log_exception(exctype, value, traceback):
    logger.error("Uncaught exception occurred!",
                 exc_info=(exctype, value, traceback))


def attach_hook(hook_func, run_func):
    def inner(*args, **kwargs):
        if not (args or kwargs):
            # This condition is for sys.exc_info
            local_args = run_func()
            hook_func(*local_args)
        else:
            # This condition is for sys.excepthook
            hook_func(*args, **kwargs)
        return run_func(*args, **kwargs)
    return inner


sys.exc_info = attach_hook(log_exception, sys.exc_info)
sys.excepthook = attach_hook(log_exception, sys.excepthook)

লগিং সেটআপটি gnu_lorien এর উত্তরে পাওয়া যাবে।


2

আমার ক্ষেত্রে (ব্যবহার করার সময় python 3) @ জ্যাকিন্ডার উত্তরটি ব্যবহার করার সময় ট্রেসব্যাকের বিষয়বস্তু মুদ্রিত হয়নি। পরিবর্তে, এটা শুধু বস্তুর নিজেই ছাপে: <traceback object at 0x7f90299b7b90>

পরিবর্তে আমি করি:

import sys
import logging
import traceback

def custom_excepthook(exc_type, exc_value, exc_traceback):
    # Do not print exception when user cancels the program
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    logging.error("An uncaught exception occurred:")
    logging.error("Type: %s", exc_type)
    logging.error("Value: %s", exc_value)

    if exc_traceback:
        format_exception = traceback.format_tb(exc_traceback)
        for line in format_exception:
            logging.error(repr(line))

sys.excepthook = custom_excepthook
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.