2011-10-10 16 views
5

से नहीं, मैं थोड़ा पाइथन आईडीई लिख रहा हूं, और मैं सरल डिबगिंग जोड़ना चाहता हूं। मुझे Winpdb की सभी सुविधाओं की आवश्यकता नहीं है। मैं लाइन नंबर पर ब्रेकपॉइंट सेट के साथ एक पायथन प्रोग्राम (फ़ाइल नाम से) कैसे लॉन्च करूं ताकि वह उस लाइन नंबर और स्टल्ट तक चलता रहे? ध्यान दें कि मैं इसे कमांड लाइन से नहीं करना चाहता, और मैं स्रोत को संपादित नहीं करना चाहता (उदाहरण के लिए set_trace डालने से)। और मैं नहीं चाहता कि यह पहली पंक्ति पर रुक जाए, इसलिए मुझे वहां से डीबगर चलाने की ज़रूरत है। मैंने पीडीबी और बीडीबी के साथ सभी स्पष्ट तरीकों का प्रयास किया है, लेकिन मुझे कुछ याद आना चाहिए।एक प्रोग्राम से एक पायथन डीबग सत्र चलाना, कंसोल

+0

तो आप कमांड लाइन का उपयोग नहीं करना चाहते हैं, और आप स्रोत को संपादित नहीं करना चाहते हैं ... आप किस और तरीके से सोच रहे हैं? – Amber

उत्तर

7

इसे करने के लिए बहुत ही व्यवहार्य तरीका (जहां तक ​​मुझे पता है) पाइथन को आपके आईडीई के भीतर से एक उपप्रोसेसर के रूप में चलाने के लिए है। यह वर्तमान पायथन दुभाषिया से "प्रदूषण" से बचाता है, जो इसे काफी हद तक संभव बनाता है कि कार्यक्रम उसी तरह से चलता है जैसे आपने इसे स्वतंत्र रूप से शुरू किया था। (आप इस के साथ कोई समस्या है तो उपप्रक्रिया वातावरण को देखें।) इस तरीके में, आप "डिबग मोड" में एक स्क्रिप्ट

p = subprocess.Popen(args=[sys.executable, '-m', 'pdb', 'scriptname.py', 'arg1'], 
        stdin=subprocess.PIPE, 
        stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE) 

का उपयोग कर यह डिबगर प्रॉम्प्ट पर अजगर से प्रारंभ हो जाएगा चला सकते हैं। , और

o,e = p.communicate('break scriptname.py:lineno') 

इस काम करता है o पायथन दुभाषिया के सामान्य उत्पादन किया जाना चाहिए के बाद यह एक ब्रेकपाइंट सेट, e चाहिए: आप कुछ डिबगर आदेशों को चलाने के लिए breakpoints, जो तुम इतनी तरह कर सकते हैं सेट करना होगा खाली रहो मेरा सुझाव है कि आप इसके साथ खेलें और यह सुनिश्चित करने के लिए कि आपके ब्रेकपॉइंट सही तरीके से सेट किए गए हैं, अपने कोड में कुछ चेक जोड़ें।

उसके बाद, आप इस बिंदु पर

p.communicate('continue') 

के साथ चल रहे कार्यक्रम शुरू कर सकते हैं तो आप शायद इनपुट, आउटपुट हुक करना चाहते हैं, और त्रुटि कंसोल है कि आप में एम्बेड कर रहे हैं अप करने के लिए धाराओं अपने आईडीई। आप शायद, एक घटना पाश के साथ ऐसा करने की आवश्यकता होगी मोटे तौर पर तो जैसे:

while p.returncode is None: 
    o,e = p.communicate(console.read()) 
    console.write(o) 
    console.write(e) 

आप को प्रभावी ढंग से स्यूडोकोड हो सकता है, पर कैसे वास्तव में अपने कंसोल काम करता है के आधार के बाद से है कि टुकड़ा पर विचार करना चाहिए, यह शायद कुछ को संवारता ले लेंगे सही से समझना।

इस जरूरत से ज्यादा गंदा लगता है, तो आप शायद प्रक्रिया को सरल कर सकते हैं एक सा पायथन के pdb और bdb मॉड्यूल की सुविधाओं का उपयोग (मेरा अनुमान है कि "अजगर डिबगर" और बुनियादी डिबगर "क्रमशः)। कैसे करना है पर सबसे अच्छा संदर्भ । pdb इस के चारों ओर एक आवरण है, यह pdb मॉड्यूल खुद के स्रोत कोड है असल में, जिस तरह से मॉड्यूल की जिम्मेदारियों को विभाजित कर रहे हैं कि bdb हैंडल डिबगर कार्यक्षमता, breakpoints सेट करना, या रोकने और निष्पादन को पुन: प्रारंभ की तरह "हुड के नीचे" है जो उपयोगकर्ता इंटरैक्शन को नियंत्रित करता है, यानी कमांड को पढ़ता है और आउटपुट प्रदर्शित करता है।

आपके आईडीई-एकीकृत डीबगर के लिए, यह adjus को समझ में आता है टी दो तरीके है कि मैं के बारे में सोच सकते हैं में pdb मॉड्यूल के व्यवहार:

  1. , आरंभीकरण के दौरान यह स्वचालित रूप से सेट breakpoints है आप स्पष्ट रूप से शाब्दिक भेजने के बिना ऐसा करने के लिए आदेश
  2. यह से इनपुट लेने और अपने आईडीई के कंसोल के लिए उत्पादन भेज

बस इन दो परिवर्तन pdb.Pdb उपवर्गीकरण से लागू करने के लिए आसान होना चाहिए।आप एक उपवर्ग जिसका प्रारंभकर्ता एक अतिरिक्त तर्क के रूप में breakpoints की एक सूची लेता बना सकते हैं:

class MyPDB(pdb.Pdb): 
    def __init__(self, breakpoints, completekey='tab', 
       stdin=None, stdout=None, skip=None): 
     pdb.Pdb.__init__(self, completekey, stdin, stdout, skip) 
     self._breakpoints = breakpoints 

तार्किक जगह वास्तव में breakpoints सेट करने में कुछ के बाद डिबगर अपने .pdbrc फ़ाइल है, जो pdb.Pdb.setup विधि में होता है पढ़ता है। वास्तविक सेटअप करने के लिए, set_break विधि bdb.Bdb से विरासत में मिली का उपयोग करें:

def setInitialBreakpoints(self): 
     _breakpoints = self._breakpoints 
     self._breakpoints = None # to avoid setting breaks twice 
     for bp in _breakpoints: 
      self.set_break(filename=bp.filename, line=bp.line, 
          temporary=bp.temporary, conditional=bp.conditional, 
          funcname=bp.funcname) 

    def setup(self, f, t): 
     pdb.Pdb.setup(self, f, t) 
     self.setInitialBreakpoints() 

कोड का यह टुकड़ा प्रत्येक ब्रेकपाइंट के लिए काम करेगा जैसे के रूप में पारित किया जा रहा एक नामित tuple। आप सीधे bdb.Breakpoint उदाहरणों का निर्माण करने के साथ भी प्रयोग कर सकते हैं, लेकिन मुझे यकीन नहीं है कि यह ठीक से काम करेगा, क्योंकि bdb.Bdb ब्रेकपॉइंट्स के बारे में अपनी जानकारी बनाए रखता है।

अगला, आपको अपने मॉड्यूल के लिए एक नया main विधि बनाना होगा जो इसे pdb रनों के समान ही चलाता है। कुछ हद तक, आप main विधि pdb (और if __name__ == '__main__' बयान के पाठ्यक्रम) की प्रतिलिपि बना सकते हैं, लेकिन आपको अपने अतिरिक्त ब्रेकपॉइंट्स के बारे में जानकारी को पास करने के लिए इसे किसी भी तरीके से बढ़ाने की आवश्यकता होगी। क्या मेरा सुझाव है कि आपके द्वारा आईडीई से एक अस्थायी फ़ाइल के लिए breakpoints लिखने, और नाम एक दूसरे तर्क के रूप में उस फ़ाइल का गुजर रहा है: mypdb.main() में

tmpfilename = ... 
# write breakpoint info 
p = subprocess.Popen(args=[sys.executable, '-m', 'mypdb', tmpfilename, ...], ...) 
# delete the temporary file 

उसके बाद, आप कुछ इस तरह जोड़ना होगा:

def main(): 
    # code excerpted from pdb.main() 
    ... 
    del sys.argv[0] 

    # add this 
    bpfilename = sys.argv[0] 
    with open(bpfilename) as f: 
     # read breakpoint info 
     breakpoints = ... 
    del sys.argv[0] 
    # back to excerpt from pdb.main() 

    sys.path[0] = os.path.dirname(mainpyfile) 

    pdb = Pdb(breakpoints) # modified 

अब आप अपने नए डीबगर मॉड्यूल का उपयोग कर सकते हैं जैसे कि आप pdb का उपयोग करेंगे, सिवाय इसके कि आपको प्रक्रिया शुरू होने से पहले break आदेशों को स्पष्ट रूप से भेजने की आवश्यकता नहीं है। इसका लाभ यह है कि आप अपने कंसोल पर पाइथन उपप्रोसेस के मानक इनपुट और आउटपुट को सीधे हुक कर सकते हैं, अगर यह आपको ऐसा करने की अनुमति देता है।

+0

इनपुट के लिए धन्यवाद। लेकिन मुझे ValueError मिलता है: जैसे ही यह p.communicate ('जारी रखें') पर बंद फ़ाइल पर I/O ऑपरेशन होता है। clos_fds का उपयोग करना = पॉपन में झूठी मदद नहीं करता है ... –

+0

@antwin: याद रखें कि यह सब अनिवार्य रूप से छद्म कोड है। यदि आप इसे अभी भी चलाते हैं, तो निश्चित रूप से आपको सभी प्रकार की त्रुटियां मिलेंगी। आपको इसे अपने स्वयं के प्रोजेक्ट में अनुकूलित करने की ज़रूरत है, जिस तरीके से मैं आपको अपने स्रोत कोड तक पहुंच के बिना कुछ भी नहीं बता सका। –

+0

दरअसल! इसलिए मैंने आपके सुझाव को निम्नलिखित फ़ाइल में निकाला #!/Usr/bin/python आयात sys, subprocess फ़ाइल नाम = '/tmp/test.py' lineno = 4 पी = subprocess.Popen (args = [sys.executable , '-एम', 'पीडीबी', फ़ाइल नाम], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) cmd = 'ब्रेक% s:% d'% (fileName, lineno); प्रिंट cmd ओ, ई = p.communicate (cmd) p.communicate ('जारी रखें') इसे काम करना चाहिए, और मैंने पहले भी इसी तरह उपयोग किया है, लेकिन यह अभी भी ValueError देता है: बंद फ़ाइल पर I/O ऑपरेशन पहले संवाद के बाद ... –

संबंधित मुद्दे