উত্তর:
কোনও বার্তা সহ প্রেরিত ট্রেস তথ্যের সাথে বর্তমান ব্যতিক্রম লগ করতে হ্যান্ডলার / ব্লকের logging.exception
মধ্যে থেকে ব্যবহার করুন except:
।
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
logging.debug('This message should go to the log file')
try:
run_my_stuff()
except:
logging.exception('Got exception on main handler')
raise
এখন লগ ফাইলটি খুঁজছেন /tmp/logging_example.out
:
DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
File "/tmp/teste.py", line 9, in <module>
run_my_stuff()
NameError: name 'run_my_stuff' is not defined
logger = logging.getLogger('yourlogger')
করতে লিখতে logger.exception('...')
হবে ...
ব্যবহারের exc_info
বিকল্পগুলি আরও ভাল হতে পারে, সতর্কতা বা ত্রুটির শিরোনাম থেকে যায়:
try:
# coode in here
except Exception as e:
logging.error(e, exc_info=True)
exc_info=
কোয়ার্গ যাকে বলে তা আমি কখনই মনে করতে পারি না ; ধন্যবাদ!
logging.exception
আমার কাজটি সম্প্রতি আমাদের অ্যাপ্লিকেশন থেকে সমস্ত ট্রেসব্যাকস / ব্যতিক্রমগুলি লগ ইন করার জন্য আমাকে কাজ দেয়। আমি অন্যান্য কৌশলগুলি চেষ্টা করেছি যা অন্যরা অনলাইনে পোস্ট করেছিল যেমন উপরের মতো তবে একটি ভিন্ন পদ্ধতির উপর স্থির হয়েছে। উপেক্ষা করাtraceback.print_exception
।
Http://www.bbarrows.com/ এ আমার একটি লেখা আছে এ যা পড়া সহজ হবে তবে আমি এটি এখানে আটকান।
যখন আমাদের সফ্টওয়্যার বন্যের সাথে মোকাবিলা করতে পারে তার সমস্ত ব্যতিক্রম লগিংয়ের কাজ করার সময় আমি অজগর ব্যতিক্রম ট্র্যাকব্যাকগুলিকে লগ করার জন্য বিভিন্ন পদ্ধতিতে চেষ্টা করেছি। প্রথমে আমি ভেবেছিলাম লগিং কোডটি সন্নিবেশ করার জন্য পাইথন সিস্টেমের ব্যতিক্রম হুক, sys.excepthook হবে সঠিক জায়গা। আমি অনুরূপ কিছু চেষ্টা করছিলাম:
import traceback
import StringIO
import logging
import os, sys
def my_excepthook(excType, excValue, traceback, logger=logger):
logger.error("Logging an uncaught exception",
exc_info=(excType, excValue, traceback))
sys.excepthook = my_excepthook
এটি মূল থ্রেডের জন্য কাজ করেছে তবে আমি শীঘ্রই দেখতে পেলাম যে আমার প্রক্রিয়া শুরু হওয়া কোনও নতুন থ্রেডে আমার sys.excepthook উপস্থিত থাকবে না। এটি একটি বিশাল সমস্যা কারণ বেশিরভাগ সবকিছুই এই প্রকল্পের থ্রেডে ঘটে।
গুগলিং এবং প্রচুর ডকুমেন্টেশন পড়ার পরে আমার পাওয়া সবচেয়ে সহায়ক তথ্য পাইথন ইস্যু ট্র্যাকার থেকে।
থ্রেডের প্রথম পোস্টটি sys.excepthook
থ্রেডগুলি জুড়ে না রাখার একটি কার্যকারী উদাহরণ দেখায় (নীচে দেখানো হয়েছে)। স্পষ্টতই এটি প্রত্যাশিত আচরণ।
import sys, threading
def log_exception(*args):
print 'got exception %s' % (args,)
sys.excepthook = log_exception
def foo():
a = 1 / 0
threading.Thread(target=foo).start()
এই পাইথন ইস্যু থ্রেডে থাকা বার্তাগুলি সত্যিই 2 টি প্রস্তাবিত হ্যাকের ফলস্বরূপ। Thread
ব্যতিক্রম বা বানরের প্যাচ ধরতে এবং লগ করার জন্য ব্লক ব্যতীত সাবক্লাস এবং রান পদ্ধতিটি আমাদের নিজের পদ্ধতিতে মোড়ক করুনthreading.Thread.run
ব্লক এবং ব্যতিক্রমগুলি লগ ব্যতীত আপনার নিজের চেষ্টা চালানোর জন্য ।
সাবক্লাসিংয়ের প্রথম পদ্ধতিটি আপনার কোডটিতে Thread
আমার কাছে কম মার্জিত বলে মনে হচ্ছে কারণ আপনি নিজের কাস্টম Thread
ক্লাসটি আমদানি করতে এবং ব্যবহার করতে হবে যেখানেই আপনি লগিংয়ের থ্রেড রাখতে চেয়েছিলেন। এটি একটি ঝামেলা হিসাবে শেষ হয়েছে কারণ আমাকে আমাদের পুরো কোড বেসটি অনুসন্ধান করতে হয়েছিল এবং Threads
এই কাস্টমটির সাথে সমস্ত স্বাভাবিক প্রতিস্থাপন করতে হয়েছিল Thread
। তবে এটি কী Thread
করছে সে সম্পর্কে এটি স্পষ্ট ছিল এবং কাস্টম লগিং কোডটিতে কোনও সমস্যা হয়ে থাকলে কারও জন্য নির্ণয় এবং ডিবাগ করা সহজ হবে। একটি গ্রাহক লগিং থ্রেড এর মতো দেখতে পারে:
class TracebackLoggingThread(threading.Thread):
def run(self):
try:
super(TracebackLoggingThread, self).run()
except (KeyboardInterrupt, SystemExit):
raise
except Exception, e:
logger = logging.getLogger('')
logger.exception("Logging an uncaught exception")
বানর প্যাচিংয়ের দ্বিতীয় পদ্ধতিটি দুর্দান্ত threading.Thread.run
কারণ আমি ঠিক এটির পরে একবার চালাতে পারি __main__
এবং সমস্ত ব্যাতিক্রমে আমার লগিং কোডটি ব্যবহার করতে পারি। বানরের প্যাচিং ডিবাগ করতে বিরক্তিকর হতে পারে যদিও এটি কোনও কিছুর প্রত্যাশিত কার্যকারিতা পরিবর্তন করে। পাইথন ইস্যু ট্র্যাকারের প্রস্তাবিত প্যাচটি হ'ল:
def installThreadExcepthook():
"""
Workaround for sys.excepthook thread bug
From
http://spyced.blogspot.com/2007/06/workaround-for-sysexcepthook-bug.html
(https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470).
Call once from __main__ before creating any threads.
If using psyco, call psyco.cannotcompile(threading.Thread.run)
since this replaces a new-style class method.
"""
init_old = threading.Thread.__init__
def init(self, *args, **kwargs):
init_old(self, *args, **kwargs)
run_old = self.run
def run_with_except_hook(*args, **kw):
try:
run_old(*args, **kw)
except (KeyboardInterrupt, SystemExit):
raise
except:
sys.excepthook(*sys.exc_info())
self.run = run_with_except_hook
threading.Thread.__init__ = init
আমি আমার ব্যতিক্রম লগিং পরীক্ষা করা শুরু না করেই বুঝতে পেরেছিলাম যে আমি এটির সমস্ত ভুল করছি।
পরীক্ষা করার জন্য আমি একটি ছিল
raise Exception("Test")
আমার কোড কোথাও। যাইহোক, আ পদ্ধতিটি যাকে এই পদ্ধতিটি বলা হয় মোড়ানো সেটি ব্লক ব্যতীত চেষ্টা ছিল যা ট্রেসব্যাক প্রিন্ট করে ব্যতিক্রমটিকে গ্রাস করে। এটি খুব হতাশার কারণ আমি দেখেছিলাম যে ট্রেসব্যাকটি এসটিডিওউটে প্রিন্ট করা হয়েছে তবে লগ হচ্ছে না। আমি তখন সিদ্ধান্ত নিয়েছিলাম যে ট্রেসব্যাকগুলি লগ করার একটি সহজ পদ্ধতি হ'ল কেবল বানরটি প্যাচ করা যা সমস্ত পাইথন কোডটি ট্রেসব্যাকগুলি তাদের মুদ্রণের জন্য ব্যবহার করে, ট্রেসব্যাক.প্রিন্ট_সেপশন। আমি নিম্নলিখিত অনুরূপ কিছু দিয়ে শেষ করেছি:
def add_custom_print_exception():
old_print_exception = traceback.print_exception
def custom_print_exception(etype, value, tb, limit=None, file=None):
tb_output = StringIO.StringIO()
traceback.print_tb(tb, limit, tb_output)
logger = logging.getLogger('customLogger')
logger.error(tb_output.getvalue())
tb_output.close()
old_print_exception(etype, value, tb, limit=None, file=None)
traceback.print_exception = custom_print_exception
এই কোডটি একটি স্ট্রিং বাফারকে ট্রেসব্যাক লিখে এবং এটি লগিং ইআরআরএর জন্য লগ করে। আমার কাছে একটি কাস্টম লগিং হ্যান্ডলার রয়েছে 'কাস্টমলগার' লগার সেটআপ করা যা ERROR স্তরের লগগুলি নিয়ে যায় এবং বিশ্লেষণের জন্য তাদের বাড়িতে পাঠায় send
add_custom_print_exception
আপনি লিঙ্ক করেছেন এমন সাইটে উপস্থিত হবে না এবং এর পরিবর্তে সেখানে বেশ কিছু ভিন্ন চূড়ান্ত কোড রয়েছে। আপনি কোনটি বলবেন ভাল / আরও চূড়ান্ত এবং কেন? ধন্যবাদ!
logger.error(traceback.format_tb())
(বা format_exc () যদি আপনি ব্যতিক্রম তথ্যও চান) want
আপনি প্রধান থ্রেডে সমস্ত অপ্রকাশিত ব্যতিক্রম ল্যান্ড করতে পারেন কোনও হ্যান্ডলারকে sys.excepthook
, সম্ভবত exc_info
পাইথনের লগিং ফাংশনগুলির পরামিতি ব্যবহার করে :
import sys
import logging
logging.basicConfig(filename='/tmp/foobar.log')
def exception_hook(exc_type, exc_value, exc_traceback):
logging.error(
"Uncaught exception",
exc_info=(exc_type, exc_value, exc_traceback)
)
sys.excepthook = exception_hook
raise Exception('Boom')
তবে যদি আপনার প্রোগ্রামটি থ্রেড ব্যবহার করে তবে থ্রেড ব্যবহার করে তৈরি করা উচিত threading.Thread
পাইথনের ইস্যু ট্র্যাকারের 1230540 ইস্যুতে উল্লিখিত হিসাবে, যখন সেগুলির মধ্যে কোনও অপ্রকাশিত ব্যতিক্রম ঘটে তখন ট্রিগার করবে না । কিছু হ্যাককে এই সীমাবদ্ধতার আশেপাশের কাজ করার পরামর্শ দেওয়া হয়েছে, যেমন একটি বিকল্প পদ্ধতিতে ওভাররাইট করার জন্য বানর-প্যাচিং যা কোনও ব্লকে আসলটি আবৃত করে এবং ব্লকের ভিতরে থেকে কল করে । বিকল্পভাবে, আপনি কেবল নিজের / নিজের নিজের প্রতিটি থ্রেডের জন্য প্রবেশের পয়েন্টটি ম্যানুয়ালি মুড়ে দিতে পারেন ।sys.excepthook
Thread.__init__
self.run
run
try
sys.excepthook
except
try
except
অপ্রকাশিত ব্যতিক্রম বার্তাগুলি STDERR এ যায়, সুতরাং পাইথনে নিজেই আপনার লগিং প্রয়োগের পরিবর্তে আপনি নিজের পাইথন স্ক্রিপ্টটি চালানোর জন্য যা কিছু শেল ব্যবহার করছেন তা ব্যবহার করে আপনি কোনও ফাইলে এসটিডিআরআর প্রেরণ করতে পারেন। বাশ স্ক্রিপ্টে, আপনি এটি আউটপুট পুনর্নির্দেশের সাহায্যে করতে পারেন, যেমন BASH গাইডে বর্ণিত ।
টার্মিনালে ফাইলগুলি ত্রুটি, অন্যান্য আউটপুট যুক্ত করুন:
./test.py 2>> mylog.log
ইন্টারলিভড STDOUT এবং STDERR আউটপুট সহ ফাইলটি ওভাররাইট করুন:
./test.py &> mylog.log
আমি যা খুঁজছিলাম:
import sys
import traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback_in_var = traceback.format_tb(exc_traceback)
দেখা:
আপনি যেকোন পর্যায়ে (ডিইবিইউজি, ইনফো, ...) লগার ব্যবহার করে ট্রেসব্যাক পেতে পারেন। নোট করুন যে ব্যবহার করে logging.exception
, স্তরটি ERROR।
# test_app.py
import sys
import logging
logging.basicConfig(level="DEBUG")
def do_something():
raise ValueError(":(")
try:
do_something()
except Exception:
logging.debug("Something went wrong", exc_info=sys.exc_info())
DEBUG:root:Something went wrong
Traceback (most recent call last):
File "test_app.py", line 10, in <module>
do_something()
File "test_app.py", line 7, in do_something
raise ValueError(":(")
ValueError: :(
সম্পাদনা করুন:
এটি খুব কার্যকর হয় (অজগর 3.6 ব্যবহার করে)
logging.debug("Something went wrong", exc_info=True)
এখানে একটি সংস্করণ যা sys.excepthook ব্যবহার করে
import traceback
import sys
logger = logging.getLogger()
def handle_excepthook(type, message, stack):
logger.error(f'An unhandled exception occured: {message}. Traceback: {traceback.format_tb(stack)}')
sys.excepthook = handle_excepthook
{traceback.format_exc()}
পরিবর্তে ব্যবহার সম্পর্কে {traceback.format_tb(stack)}
?
সম্ভবত হিসাবে আড়ম্বরপূর্ণ না, কিন্তু সহজ:
#!/bin/bash
log="/var/log/yourlog"
/path/to/your/script.py 2>&1 | (while read; do echo "$REPLY" >> $log; done)
পাইথন ২.6 নথি থেকে গৃহীত একটি সহজ উদাহরণ :
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
logging.debug('This message should go to the log file')