2009-08-20 18 views
10

यह एक बेकार दावा त्रुटि है; यह शामिल अभिव्यक्ति के मूल्यों बता नहीं करता है (स्थिरांक मान इस्तेमाल किया वास्तव में चर नाम हैं):पायथन जोर - विफलता के आत्मनिरीक्षण में सुधार?

$ python -c "assert 6-(3*2)" 
[...] 
AssertionError 

वहाँ पायथन में एक बेहतर assert कार्यान्वयन कि अधिक कल्पना है? इसे निष्पादन पर अतिरिक्त ओवरहेड नहीं पेश करना चाहिए (जब दावा विफल हो जाता है) .. और -O ध्वज का उपयोग होने पर बंद होना चाहिए।

संपादित करें: मुझे स्ट्रिंग के रूप में जोर के दूसरे तर्क के बारे में पता है। मैं एक लिखना नहीं चाहता .. क्योंकि यह अभिव्यक्ति में एन्कोड किया गया है जिसे जोर दिया जा रहा है। DRY (खुद को दोहराएं मत)।

उत्तर

5

आप एक assert के लिए एक संदेश संलग्न कर सकते हैं:

assert 6-(3*2), "always fails" 

संदेश भी गतिशील रूप से बनाया जा सकता है:

assert x != 0, "x is not equal to zero (%d)" % x 

अधिक जानकारी के लिए अजगर दस्तावेज में The assert statement देखें।

+0

, मैं इस में पता था। मैं एक लिखना नहीं चाहता क्योंकि यह अभिव्यक्ति में एन्कोड किया गया है जिसे जोर दिया जा रहा है। सूखी। –

+0

मैं देखता हूं कि आपका क्या मतलब है। मुझे विश्वास नहीं है कि पाइथन के पास ऐसा करने का एक तरीका है। –

0

अपने दावे, जो प्रदर्शित किया जाएगा करने के लिए एक संदेश जोड़ें यदि दावे विफल रहता है:

$ python -c "assert 6-(3*2), '6-(3*2)'" 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
AssertionError: 6-(3*2) 

एक ही रास्ता मैं के बारे में सोच सकते हैं कि यह स्वचालित रूप से प्रदान करने के लिए एक प्रक्रिया कॉल में दावा को रोकने के लिए होगा, और फिर उस रेखा के लिए स्रोत कोड प्राप्त करने के लिए ढेर का निरीक्षण करें। दुर्भाग्यवश, अतिरिक्त कॉल परीक्षण में ओवरहेड पेश करेगा और -O के साथ अक्षम नहीं होगा।

+0

निश्चित रूप से। यह इस 'आत्मनिरीक्षण' को अक्षम कर रहा है -ओ कि प्रश्न की कुंजी है। –

+0

.. लेकिन यह एक ओवरहेड नहीं है अगर यह फ़ंक्शन केवल दावा त्रुटियों के दौरान कहा जाता है (दावा कॉल नहीं)। –

4

The nose testing suite applies introspection to asserts। में

 
C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py 
F 
====================================================================== 
FAIL: test.test1 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 
183, in runTest 
    self.test(*self.arg) 
    File "C:\temp\py\test.py", line 3, in test1 
    nose.tools.assert_equal(6, 5+2) 
AssertionError: 6 != 7 
>> raise self.failureException, \ 
      (None or '%r != %r' % (6, 7)) 

सूचना AssertionError वहाँ

import nose 
def test1(): 
    nose.tools.assert_equal(6, 5+2) 

परिणाम:

हालांकि, AFAICT, आप कॉल करना उनके आत्मनिरीक्षण प्राप्त करने के लिए इस बात पर ज़ोर दिया है। जब मेरी लाइन बस assert 6 == 5+2 था, मैं मिलेगा:

 
C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py 
F 
====================================================================== 
FAIL: test.test1 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 
183, in runTest 
    self.test(*self.arg) 
    File "C:\temp\py\test.py", line 2, in test1 
    assert 6 == 5 + 2 
AssertionError: 
>> assert 6 == 5 + 2 

इसके अलावा, मैं नहीं यकीन है कि बेतकल्लुफ़ पाता है अगर उनकी -O साथ छोड़ दिया गया है, लेकिन यह एक बहुत त्वरित जांच होगी।

+0

परीक्षण के मामलों के लिए पर्याप्त है, लेकिन उत्पादन कोड के लिए .. फ़ंक्शन कॉल ओवरहेड है (यहां तक ​​कि ओओ विकल्प के साथ) –

+4

साधारण आवेषण भी काम करते हैं। Http://stackoverflow.com/questions/1308607/python-assert-improved-introspection-of-failure/1309039#1309039 – jfs

7

@Mark Rushakoff saidnose विफल आक्रमणों का मूल्यांकन कर सकते हैं। यह मानक assert पर भी काम करता है।

# test_error_reporting.py 
def test(): 
    a,b,c = 6, 2, 3 
    assert a - b*c 

nosetests की मदद:

$ nosetests --help|grep -B2 assert 
    -d, --detailed-errors, --failure-detail 
         Add detail to error output by attempting to evaluate 
         failed asserts [NOSE_DETAILED_ERRORS] 

उदाहरण:

$ nosetests -d 
F 
====================================================================== 
FAIL: test_error_reporting.test 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "..snip../site-packages/nose/case.py", line 183, in runTest 
    self.test(*self.arg) 
    File "..snip../test_error_reporting.py", line 3, in test 
    assert a - b*c 
AssertionError: 
    6,2,3 = 6, 2, 3 
>> assert 6 - 2*3 


---------------------------------------------------------------------- 
Ran 1 test in 0.089s 

FAILED (failures=1) 
+0

प्रश्न यह है कि प्रश्न कोड में जोर देने के उपयोग के संबंध में है (जिसे उपयोगकर्ता द्वारा सीधे बुलाया जाता है) उदाहरण के लिए, ./foo.py .. या विंडोज एक्सप्लोरर पर 'foo.pyw' पर क्लिक करना), और परीक्षण कोड नहीं .. जिसके लिए मैं वास्तव में py.test के आवेषण आउटपुट से खुश हूं। –

+1

@srid: इस मामले में लिखें: '__debug__ और your_fancy_assert (अभिव्यक्ति)' - '-O' पर कोई ओवरहेड नहीं। – jfs

+0

यह दिलचस्प लगता है; बहुत खराब पायथन में 'मैक्रो' सुविधा नहीं है। –

10

sys.excepthook के रूप में समारोह की अपनी स्थापित करें - the docs देखते हैं।आपका कार्य, यदि दूसरा तर्क AssertionError है, तो आपके दिल की सामग्री का आत्मनिरीक्षण कर सकता है; विशेष रूप से, तीसरे तर्क के माध्यम से, ट्रेसबैक, यह फ्रेम और सटीक स्थान प्राप्त कर सकता है जिसमें जोर विफल हो गया है, स्रोत या बाइटकोड के माध्यम से असफल अपवाद प्राप्त करना, सभी प्रासंगिक चर के मूल्य आदि। मॉड्यूल inspect मदद करता है।

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

+1

अच्छा। अब इसके लिए एक पायथन पुस्तकालय है .. या क्या मुझे अपना खुद लिखना है? :-) (मैं शायद नहीं .. क्योंकि यह मेरे लिए एक कम-प्राइयो कार्य है) –

+0

दुर्भाग्यवश मुझे यह सब करने के लिए मौजूदा पायथन पुस्तकालयों के बारे में पता नहीं है, परीक्षण करने के लिए उन्मुख लोगों को छोड़कर (जिसे अनुकूलित किया जाना पड़ सकता है उत्पादन कोड पर उनका उपयोग करने के उद्देश्य से)। –

0

ऐसा लगता है कि आप वास्तव में क्या करना चाहते हैं assert से पहले एक डीबगर ब्रेकपॉइंट सेट अप करना और अपने पसंदीदा डीबगर से जितना चाहें उतना निरीक्षण करें।

0

मैंने sys.excepthook (जिसे किसी भी अनचाहे अपवाद के लिए बुलाया जाता है) के प्रतिस्थापन को कोड किया है जो मानक एक से थोड़ा अधिक फैंसी है। यह उस लाइन का विश्लेषण करेगा जहां अपवाद हुआ था और इस पंक्ति में संदर्भित सभी चर प्रिंट करें (यह सभी स्थानीय चर मुद्रित नहीं करता है क्योंकि यह बहुत अधिक शोर हो सकता है - शायद, महत्वपूर्ण var वैश्विक या तो हो)।

मैंने इसे py_better_exchook (सही नाम) कहा और यह here है।

उदाहरण फ़ाइल:

a = 6 

def test(): 
    unrelated_var = 43 
    b,c = 2, 3 
    assert a - b*c 

import better_exchook 
better_exchook.install() 

test() 

आउटपुट:

$ python test_error_reporting.py 
EXCEPTION 
Traceback (most recent call last): 
    File "test_error_reporting.py", line 12, in <module> 
    line: test() 
    locals: 
     test = <local> <function test at 0x7fd91b1a05f0> 
    File "test_error_reporting.py", line 7, in test 
    line: assert a - b*c 
    locals: 
     a = <global> 6 
     b = <local> 2 
     c = <local> 3 
AssertionError 
बेशक
संबंधित मुद्दे