मेरे पास यह पायथन एप्लिकेशन है जो समय-समय पर अटक जाता है और मुझे यह पता नहीं चल पाता है कि कहां है।
क्या पायथन दुभाषिया को संकेत देने का कोई तरीका है जो आपको सही कोड दिखा रहा है?
किसी तरह का ऑन-द-स्टैकट्रेस?
संबंधित सवाल:
मेरे पास यह पायथन एप्लिकेशन है जो समय-समय पर अटक जाता है और मुझे यह पता नहीं चल पाता है कि कहां है।
क्या पायथन दुभाषिया को संकेत देने का कोई तरीका है जो आपको सही कोड दिखा रहा है?
किसी तरह का ऑन-द-स्टैकट्रेस?
संबंधित सवाल:
जवाबों:
मेरे पास इस तरह की स्थितियों के लिए उपयोग किए जाने वाले मॉड्यूल हैं - जहां एक प्रक्रिया लंबे समय तक चल रही होगी, लेकिन कभी-कभी अज्ञात और अपूरणीय कारणों से अटक जाती है। इसका थोड़ा सा हैकी है, और केवल यूनिक्स पर काम करता है (संकेतों की आवश्यकता है):
import code, traceback, signal
def debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
i = code.InteractiveConsole(d)
message = "Signal received : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.SIGUSR1, debug) # Register handler
उपयोग करने के लिए, जब आपका प्रोग्राम शुरू होता है, तो किसी समय बस सुनने () फ़ंक्शन को कॉल करें (आप इसे साइट-थ्रू में भी चिपका सकते हैं, ताकि सभी पायथन प्रोग्राम इसका उपयोग कर सकें), और इसे चलने दें। किसी भी बिंदु पर, प्रक्रिया को SIGUSR1 सिग्नल भेजें, किल का उपयोग करके, या अजगर में:
os.kill(pid, signal.SIGUSR1)
यह उस समय इस बिंदु पर एक अजगर कंसोल को तोड़ने का कारण बनेगा, जो आपको स्टैक ट्रेस दिखा रहा है, और आपको चर में हेरफेर करने की अनुमति देता है। कंट्रोल-डी (ईओएफ) का उपयोग चालू रखने के लिए करें (हालांकि ध्यान दें कि आप संभवतः उस बिंदु पर कोई I / O इत्यादि को इंगित करेंगे जो आप संकेत करते हैं, इसलिए यह पूरी तरह से गैर-घुसपैठ नहीं है।
मेरे पास एक और स्क्रिप्ट है जो समान काम करती है, सिवाय इसके कि यह एक पाइप के माध्यम से चल रही प्रक्रिया के साथ संचार करती है (पृष्ठभूमि की प्रक्रियाओं को डीबग करने के लिए अनुमति देने के लिए)। यहाँ पोस्ट करने के लिए यह थोड़ा बड़ा है, लेकिन मैंने इसे पाइथन कुकबुक रेसिपी के रूप में जोड़ा है ।
faulthandler
C स्तर सिग्नल हैंडलर के लिए मॉड्यूल (और इसका बैकपोर्ट PyPI पर पाया गया) का उपयोग करें जो कि इंटरप्रिटर लूप को उत्तरदायी बनाए बिना पायथन स्टैक को प्रिंट करेगा।
सिग्नल हैंडलर लगाने का सुझाव एक अच्छा है, और मैं इसका भरपूर उपयोग करता हूं। उदाहरण के लिए, BzR डिफ़ॉल्ट रूप से एक SIGQUIT हैंडलर कि आह्वान को स्थापित करता है pdb.set_trace()
तुरंत एक में आप ड्रॉप करने pdb शीघ्र। ( सटीक विवरण के लिए bzrlib.breakin मॉड्यूल का स्रोत देखें।) पीडीबी के साथ आप न केवल वर्तमान स्टैक ट्रेस प्राप्त कर सकते हैं, बल्कि चर आदि का भी निरीक्षण कर सकते हैं।
हालांकि, कभी-कभी मुझे एक प्रक्रिया को डीबग करने की आवश्यकता होती है, जिसमें सिग्नल हैंडलर को स्थापित करने के लिए मेरे पास दूरदर्शिता नहीं थी। लिनक्स पर, आप प्रक्रिया में जीडीबी संलग्न कर सकते हैं और कुछ जीडीबी मैक्रोज़ के साथ एक अजगर स्टैक ट्रेस प्राप्त कर सकते हैं। Http://svn.python.org/projects/python/trunk/Misc/gdbinit को इसमें डालें ~/.gdbinit
:
gdb -p
PID
pystack
यह दुर्भाग्य से पूरी तरह से विश्वसनीय नहीं है, लेकिन यह ज्यादातर समय काम करता है।
अंत में, संलग्न करना strace
आपको अक्सर एक अच्छा विचार दे सकता है कि एक प्रक्रिया क्या कर रही है।
python-dbg
) के साथ चलाया । उन प्रतीकों के बिना, आपको बहुत उपयोगी जानकारी नहीं मिलती है।
Unable to locate python frame
प्रत्येक आदेश पर वापस
मैं लगभग हमेशा कई थ्रेड्स के साथ काम कर रहा हूं और मुख्य धागा आम तौर पर बहुत कुछ नहीं कर रहा है, इसलिए जो सबसे दिलचस्प है वह सभी स्टैक को डंप करना है (जो कि जावा के डंप की तरह अधिक है)। यहाँ इस ब्लॉग पर आधारित एक कार्यान्वयन है :
import threading, sys, traceback
def dumpstacks(signal, frame):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
एक अप्रकाशित अजगर कार्यक्रम का स्टैक ट्रेस करना, प्रतीकों को डिबग किए बिना एक स्टॉक अजगर में चलना पायरसाइट के साथ किया जा सकता है । उबंटू ट्रस्टी में मेरे लिए एक आकर्षण की तरह काम किया:
$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
$ sudo pyrasite 16262 dump_stacks.py # dumps stacks to stdout/stderr of the python program
(हैट टिप टू @Albert, जिसके उत्तर में अन्य उपकरणों के बीच एक सूचक था।)
dump_stacks.py
वह बस थीimport traceback; traceback.print_stack()
traceback -l
आपको पूर्वनिर्धारित अजगर लिपियों की एक सूची देता है जिसका आप उपयोग कर सकते हैं, और dump_stacks.py
उनमें से एक है। यदि आप अपना स्वयं का उपयोग कर रहे हैं (उदाहरण के लिए किसी फ़ाइल के लिए स्टैक ट्रेस लिखने के लिए) तो एक अलग नाम का उपयोग करना बुद्धिमान हो सकता है।
apt-get install gdb python-dbg
पाइरसाइट चलाने से पहले चलाएं (या समतुल्य), अन्यथा यह चुपचाप विफल हो जाएगा। एक आकर्षण की तरह काम करता है अन्यथा!
>>> import traceback
>>> def x():
>>> print traceback.extract_stack()
>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]
आप स्टैक ट्रेस को अच्छी तरह से प्रारूपित कर सकते हैं, डॉक्स देख सकते हैं ।
संपादित करें : @Douglas Leeder द्वारा सुझाए गए जावा के व्यवहार का अनुकरण करने के लिए, इसे जोड़ें:
import signal
import traceback
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
आपके आवेदन में स्टार्टअप कोड के लिए। फिर आप SIGUSR1
चल रहे पायथन प्रक्रिया को भेजकर स्टैक प्रिंट कर सकते हैं।
ट्रैस बैक मॉड्यूल उन के बीच में कुछ अच्छा काम करता है, है: print_stack:
import traceback
traceback.print_stack()
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
आप गलती करने वाले मॉड्यूल की कोशिश कर सकते हैं । इसका उपयोग करके स्थापित करें pip install faulthandler
और जोड़ें:
import faulthandler, signal
faulthandler.register(signal.SIGUSR1)
अपने कार्यक्रम की शुरुआत में। फिर SIGUSR1 को अपनी प्रक्रिया में भेजें (उदा:) kill -USR1 42
सभी थ्रेड्स के पायथन ट्रेसबैक को मानक आउटपुट में प्रदर्शित करने के लिए। अधिक विकल्पों के लिए प्रलेखन पढ़ें (उदा: फ़ाइल में लॉग इन करें) और ट्रेसबैक प्रदर्शित करने के अन्य तरीके।
मॉड्यूल अब पायथन 3.3 का हिस्सा है। अजगर 2 के लिए, http://faulthandler.readthedocs.org/ देखें
क्या वास्तव में यहाँ मेरी मदद की गई है स्पिव्स टिप (जिसे मैं वोट करूंगी और टिप्पणी करूंगी कि अगर मेरे पास प्रतिष्ठा अंक हैं) तो एक अनपेक्षित पायथन प्रक्रिया से बाहर एक स्टैक ट्रेस पाने के लिए । सिवाय यह तब तक काम नहीं आया जब तक मैंने gdbinit स्क्रिप्ट को संशोधित नहीं किया । इसलिए:
http://svn.python.org/projects/python/trunk/Misc/gdbinit डाउनलोड करें और इसे डालें~/.gdbinit
इसे संपादित करें, में बदल रहा [संपादित करें: अब ज़रूरत नहीं है; लिंक की गई फ़ाइल में पहले से ही 2010-01-14 के अनुसार यह परिवर्तन है]PyEval_EvalFrame
हैPyEval_EvalFrameEx
जीडीबी संलग्न करें: gdb -p PID
अजगर स्टैक ट्रेस प्राप्त करें: pystack
No symbol "co" in current context.
मैं इसे हर्षदेव की प्रतिक्रिया के लिए एक टिप्पणी के रूप में जोड़ूंगा , लेकिन मुझे ऐसा करने के लिए प्रतिष्ठा की कमी है:
हममें से कुछ अभी भी 2.6 से अधिक उम्र के पायथन के एक संस्करण पर अटके हुए हैं (थ्रेड के लिए आवश्यक), इसलिए मुझे पायथन 2.5 में काम करने वाला कोड मिल गया (हालांकि थ्रेड नाम प्रदर्शित किए बिना) जैसे:
import traceback
import sys
def dumpstacks(signal, frame):
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %d" % (threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
python -dv yourcript.py
यह दुभाषिया को डिबग मोड में चलाने के लिए और दुभाषिया क्या कर रहा है, इसका पता लगाने के लिए करेगा।
यदि आप कोड को अंतःक्रियात्मक रूप से डिबग करना चाहते हैं, तो आपको इसे इस तरह चलाना चाहिए:
python -m pdb yourcript.py
यह आपकी स्क्रिप्ट को मॉड्यूल "pdb" के साथ चलाने के लिए अजगर इंटरप्रेटर को बताता है जो कि अजगर डीबगर है, अगर आप इसे इस तरह से चलाते हैं कि इंटरप्रेटर इंटरएक्टिव मोड में निष्पादित होगा, तो GDB की तरह
faulthandler
मॉड्यूल पर एक नज़र डालें , पायथन 3.3 में नया। Python 2 में उपयोग के लिए एक faulthandler
बैकपोर्ट PyPI पर उपलब्ध है।
सोलारिस पर, आप pstack का उपयोग कर सकते हैं (1) अजगर कोड में कोई परिवर्तन आवश्यक नहीं है। जैसे।
# pstack 16000 | grep : | head
16000: /usr/bin/python2.6 /usr/lib/pkg.depotd --cfg svc:/application/pkg/serv
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:282 (_wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:295 (wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:242 (block) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/_init_.py:249 (quickstart) ]
[ /usr/lib/pkg.depotd:890 (<module>) ]
[ /usr/lib/python2.6/threading.py:256 (wait) ]
[ /usr/lib/python2.6/Queue.py:177 (get) ]
[ /usr/lib/python2.6/vendor-packages/pkg/server/depot.py:2142 (run) ]
[ /usr/lib/python2.6/threading.py:477 (run)
etc.
pstack
है जो एक ही काम करता है
यदि आप लिनक्स सिस्टम पर हैं, तो gdb
पायथन डीबग एक्सटेंशन (यह python-dbg
या python-debuginfo
पैकेज में हो सकता है ) के साथ अजीबता का उपयोग करें । यह मल्टीथ्रेड एप्लिकेशन, GUI एप्लिकेशन और C मॉड्यूल के साथ भी मदद करता है।
इसके साथ अपना कार्यक्रम चलाएं:
$ gdb -ex r --args python <programname>.py [arguments]
इसे gdb
तैयार करने python <programname>.py <arguments>
और r
इसे एकजुट करने का निर्देश दिया।
अब जब आप प्रोग्राम लटकाते हैं, तो gdb
कंसोल में स्विच करें , प्रेस करें Ctr+Cऔर निष्पादित करें:
(gdb) thread apply all py-list
देखें उदाहरण के सत्र और अधिक जानकारी के लिए यहाँ और यहाँ ।
मैं अपने थ्रेड्स को डीबग करने के समाधान के लिए कुछ समय के लिए देख रहा था और मैंने इसे यहां पाया कि हार्डीसव के लिए धन्यवाद। मैं ट्रेसबैक.प्रिंट_स्टैक () को नियोजित करने के लिए थोड़ा सरलीकृत संस्करण का उपयोग करता हूं:
import sys, traceback, signal
import threading
import os
def dumpstacks(signal, frame):
id2name = dict((th.ident, th.name) for th in threading.enumerate())
for threadId, stack in sys._current_frames().items():
print(id2name[threadId])
traceback.print_stack(f=stack)
signal.signal(signal.SIGQUIT, dumpstacks)
os.killpg(os.getpgid(0), signal.SIGQUIT)
अपनी आवश्यकताओं के लिए मैं नाम से धागे भी फ़िल्टर करता हूं।
यह Pydb को देखने लायक है , " Pybon डिबगर का एक विस्तारित संस्करण, जो कि gdb कमांड सेट पर आधारित है"। इसमें संकेत प्रबंधक शामिल हैं जो निर्दिष्ट संकेत भेजे जाने पर डिबगर शुरू करने का ध्यान रख सकते हैं।
2006 के समर कोड ऑफ़ प्रोजेक्ट प्रोजेक्ट में mpdb नामक एक मॉड्यूल में pydb को रिमोट-डिबगिंग फीचर्स को जोड़कर देखा गया ।
मैंने कुछ टूल को एक साथ हैक किया जो एक चल रहे पायथन प्रक्रिया में संलग्न होता है और पायथन शेल प्राप्त करने के लिए कुछ कोड को इंजेक्ट करता है।
यहां देखें: https://github.com/albertz/pydbattach
pyrasite
पूरी तरह से काम किया!
यह उत्कृष्ट पी-जासूस के साथ किया जा सकता है । यह पायथन कार्यक्रमों के लिए एक नमूना प्रोफाइलर है , इसलिए इसका काम एक पायथन प्रक्रियाओं से जुड़ना और उनके कॉल स्टैक्स का नमूना लेना है। इसलिए, py-spy dump --pid $SOME_PID
आपको इस $SOME_PID
प्रक्रिया में सभी थ्रेड्स के कॉल स्टैक को डंप करने की आवश्यकता है । आमतौर पर इसे बढ़ाए गए विशेषाधिकारों (लक्ष्य प्रक्रिया 'मेमोरी को पढ़ने के लिए) की आवश्यकता होती है।
यहाँ एक उदाहरण है कि यह थ्रेडेड पायथन एप्लिकेशन के लिए कैसा दिखता है।
$ sudo py-spy dump --pid 31080
Process 31080: python3.7 -m chronologer -e production serve -u www-data -m
Python v3.7.1 (/usr/local/bin/python3.7)
Thread 0x7FEF5E410400 (active): "MainThread"
_wait (cherrypy/process/wspbus.py:370)
wait (cherrypy/process/wspbus.py:384)
block (cherrypy/process/wspbus.py:321)
start (cherrypy/daemon.py:72)
serve (chronologer/cli.py:27)
main (chronologer/cli.py:84)
<module> (chronologer/__main__.py:5)
_run_code (runpy.py:85)
_run_module_as_main (runpy.py:193)
Thread 0x7FEF55636700 (active): "_TimeoutMonitor"
run (cherrypy/process/plugins.py:518)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
Thread 0x7FEF54B35700 (active): "HTTPServer Thread-2"
accept (socket.py:212)
tick (cherrypy/wsgiserver/__init__.py:2075)
start (cherrypy/wsgiserver/__init__.py:2021)
_start_http_thread (cherrypy/process/servers.py:217)
run (threading.py:865)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
...
Thread 0x7FEF2BFFF700 (idle): "CP Server Thread-10"
wait (threading.py:296)
get (queue.py:170)
run (cherrypy/wsgiserver/__init__.py:1586)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
pyringe एक डिबगर है जो बिना किसी प्राथमिकता के सेटअप के बिना अजगर प्रक्रियाओं, प्रिंट स्टैक ट्रैस, चर आदि के साथ बातचीत कर सकता है।
जबकि मैंने अक्सर सिग्नल हैंडलर समाधान का उपयोग अतीत में किया है, फिर भी कुछ वातावरणों में समस्या को पुन: उत्पन्न करना मुश्किल हो सकता है।
pyrasite
ने मेरे लिए एक आकर्षण की तरह काम किया।
चल रहे अजगर प्रक्रिया में हुक करने और उचित परिणाम प्राप्त करने का कोई तरीका नहीं है। यदि प्रक्रियाएं बंद हो जाती हैं तो मैं स्ट्रेस को हुक कर रहा हूं और यह पता लगाने की कोशिश कर रहा हूं कि वास्तव में क्या हो रहा है।
दुर्भाग्य से अक्सर स्ट्रेस प्रेक्षक होता है जो दौड़ की स्थितियों को "ठीक करता है" ताकि आउटपुट भी बेकार हो जाए।
आप ऐसा करने के लिए शाप इंटरफ़ेस के साथ PuDB , पायथन डीबगर का उपयोग कर सकते हैं । बस जोड़ दो
from pudb import set_interrupt_handler; set_interrupt_handler()
अपने कोड के लिए और जब आप ब्रेक करना चाहें तो Ctrl-C का उपयोग करें। c
यदि आप इसे याद करते हैं और फिर से प्रयास करना चाहते हैं तो आप कई बार फिर से जारी रख सकते हैं और तोड़ सकते हैं ।
मैं अजगर एक्सटेंशन के साथ GDB शिविर में हूं। Https://wiki.python.org/moin/DebuggingWithGdb को फॉलो करें , जिसका मतलब है
dnf install gdb python-debuginfo
या sudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
भी विचार info threads
और thread apply all py-bt
।
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
जब यह चल रहा हो तो प्रतिक्रिया प्राप्त करना सामान्य py-bt
है gdb
?
sudo
। मैं gdb pyton <pid>
sudo के रूप में भी चलाने की जरूरत है।
कंसोल में किसी फ़ंक्शन को डीबग कैसे करें :
फंक्शन बनाएँ जहाँ आप pdb.set_trace () का उपयोग करते हैं , फिर आप डिबग चाहते हैं।
>>> import pdb
>>> import my_function
>>> def f():
... pdb.set_trace()
... my_function()
...
फिर कॉल किए गए फ़ंक्शन:
>>> f()
> <stdin>(3)f()
(Pdb) s
--Call--
> <stdin>(1)my_function()
(Pdb)
मुबारक डिबगिंग :)
मुझे जावा के SIGQUIT की प्रतिक्रिया के समान कुछ भी नहीं पता है , इसलिए आपको इसे अपने आवेदन में बनाना होगा। हो सकता है कि आप किसी अन्य थ्रेड में एक सर्वर बना सकते हैं जो किसी प्रकार के संदेश के जवाब पर स्टैकट्रेस प्राप्त कर सकता है?
पायथन 3 में, pdb डिबगर में c (ont (inue)) का उपयोग करने के बाद पहली बार स्वचालित रूप से एक सिग्नल हैंडलर स्थापित करेगा। कंट्रोल-सी को बाद में दबाने पर आप वापस वहीं पर गिर जाएंगे। पायथन 2 में, यहां एक-लाइनर है जो अपेक्षाकृत पुराने संस्करणों में भी काम करना चाहिए (2.7 में परीक्षण किया गया था, लेकिन मैंने पायथन स्रोत को 2.4 पर वापस चेक किया और यह ठीक लग रहा था):
import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))
pdb सीखने लायक है यदि आप पायथन डिबगिंग के किसी भी समय खर्च करते हैं। इंटरफ़ेस थोड़ा ओबट्यूज़ है, लेकिन ऐसे किसी भी उपकरण से परिचित होना चाहिए जिसने gdb जैसे उपकरण का उपयोग किया हो।
यदि आपको uWSGI के साथ ऐसा करने की आवश्यकता है, तो इसमें पायथन ट्रैसेबैकर अंतर्निहित है और यह कॉन्फ़िगरेशन में इसे सक्षम करने की बात है (संख्या प्रत्येक कार्यकर्ता के लिए नाम से जुड़ी हुई है):
py-tracebacker=/var/run/uwsgi/pytrace
एक बार ऐसा करने के बाद, आप सॉकेट से कनेक्ट करके बैकट्रेस प्रिंट कर सकते हैं:
uwsgi --connect-and-read /var/run/uwsgi/pytrace1
उस बिंदु पर जहां कोड चलाया जाता है, आप इस छोटे स्निपेट को एक अच्छी तरह से प्रारूपित मुद्रित स्टैक ट्रेस देखने के लिए सम्मिलित कर सकते हैं। यह मानता है कि आपके पास logs
आपके प्रोजेक्ट की रूट डायरेक्टरी में एक फोल्डर है ।
# DEBUG: START DEBUG -->
import traceback
with open('logs/stack-trace.log', 'w') as file:
traceback.print_stack(file=file)
# DEBUG: END DEBUG --!