2010-01-05 18 views
9

मेरी अजगर कोड के लिए इस्तेमाल किया फ़ंक्शन कॉल के बहुत सारे के साथ interlaced है (डिबगिंग | रूपरेखा | अनुरेखण आदि) उदाहरण के लिए :अजगर बराबर अजगर में टिप्पणी करने के लिए एक समारोह कॉल

import logging 

logging.root.setLevel(logging.DEBUG) 
logging.debug('hello') 
j = 0 
for i in range(10): 
    j += i 
    logging.debug('i %d j %d' % (i,j)) 
print(j) 
logging.debug('bye') 

मैं कोड के बाहर इन संसाधन उपभोग कार्यों को परिभाषित करना चाहता हूं। सी की तरह कुछ बराबर

#define logging.debug(val) 

हाँ, मुझे पता है लॉगिंग मॉड्यूल लॉगिंग स्तर तंत्र सेट लॉग स्तर से नीचे loggings बाहर मुखौटा करने के लिए इस्तेमाल किया जा सकता है। लेकिन, im एक सामान्य तरीके से अजगर दुभाषिया छोड़ कार्यों के लिए के लिए पूछ

एक विचार कार्यों मैं खाली कार्यों में बाहर टिप्पणी करना चाहते हैं फिर से परिभाषित करने के लिए है (कि चलाने के लिए भले ही वे ज्यादा कुछ न समय लेने के लिए):

def lazy(*args): pass 
logging.debug = lazy 

ऊपर विचार अभी भी एक फ़ंक्शन को कॉल करने, और एक मॉड्यूल scoped चर का प्रयोग अन्य समस्याओं

उत्तर

17

पायथन में प्रीप्रोसेसर नहीं है, हालांकि आप एक ही प्रभाव प्राप्त करने के लिए बाहरी प्रीप्रोसेसर के माध्यम से अपना पायथन स्रोत चला सकते हैं - उदा। sed "/logging.debug/d" सभी डीबग लॉगिंग आदेशों को हटा देगा। हालांकि यह बहुत ही सुरुचिपूर्ण नहीं है - आपको प्रीप्रोसेसर के माध्यम से अपने सभी मॉड्यूल चलाने के लिए किसी प्रकार की बिल्ड सिस्टम की आवश्यकता समाप्त हो जाएगी और संभवतः मुख्य स्क्रिप्ट चलाने से पहले संसाधित .py फ़ाइलों का एक नया निर्देशिका पेड़ बनाएं।

वैकल्पिक रूप से यदि आप अपने सभी डीबग स्टेटमेंट को if __debug__: ब्लॉक में डालते हैं तो उन्हें ऑप्टिमाइज़ किया जाएगा जब पायथन को ओओ (ऑप्टिमाइज़) ध्वज के साथ चलाया जाता है।

एक तरफ, मैंने यह सुनिश्चित करने के लिए डी मॉड्यूल के साथ कोड की जांच की कि यह अनुकूलित हो गया है।मुझे पता चला कि दोनों

if __debug__: doStuff() 

और

if 0: doStuff() 

अनुकूलित कर रहे हैं, लेकिन

if False: doStuff() 

नहीं है। इसका कारण यह है झूठी एक नियमित रूप से अजगर वस्तु है, और आप वास्तव में यह कर सकते हैं:

>>> False = True 
>>> if False: print "Illogical, captain" 
Illogical, captain 

कौन सा मेरे लिए भाषा में एक दोष लगता है - उम्मीद है कि यह अजगर में तय हो गई है 3.

संपादित करें:

यह पायथन 3 में तय किया गया है: सही या गलत now gives a SyntaxError पर असाइन करना। के बाद से यह सच है और झूठी अजगर 3 में स्थिरांक हैं, इसका मतलब है कि अब if False: doStuff() अनुकूलित है:

>>> def f(): 
...  if False: print("illogical") 
... 
>>> dis.dis(f) 
    2   0 LOAD_CONST    0 (None) 
       3 RETURN_VALUE   
+0

में फ़ंक्शन को टिप्पणी करने का एक सामान्य उद्देश्य तरीका बग करता है यह पाइथन 3 में काम करता है। – Brian

+0

यदि 0: 0 की तैयारी कर रहा है। अगर __debug__: | यदि परिवर्तनीय: + अनुकूलन, चाहे किसी स्क्रिप्ट या अच्छे संपादक के माध्यम से सबसे अच्छा विचार हो (प्रीपेन्डिंग # से बेहतर जो बहु पंक्ति विवरणों को संभाल नहीं करता है)।हो सकता है कि सभी –

+1

@ डेव के बाद पाइथन सही नहीं है: एक अच्छा पायथन वायरस कोड में 'गलत, सही = सही, गलत' रेखा को इंजेक्ट करेगा। अद्भुत चीजें हो सकती हैं –

0

के असंख्य बना सकते हैं?

from config_module import debug_flag

और लॉगिंग समारोह (रों) के लिए द्वार का उपयोग करने के लिए इस "चर" का उपयोग करें। आप स्वयं को logging मॉड्यूल का निर्माण करेंगे जो लॉगिंग कार्यक्षमता को गेट करने के लिए debug_flag का उपयोग करता है।

+0

तो मैं हर कार्य कॉल करने से पहले एक जांच जोड़ना होगा? –

+0

@ यादृच्छिक लड़का: इन सभी डीबग बयान के साथ पहले से ही गंदे है ?? – cschol

+0

@jldupont: क्या मुझे अपने रैपर वर्ग में लॉग इन करने के लिए सभी कॉलों को बदलना नहीं होगा? –

0

मुझे लगता है कि एक फ़ंक्शन पर कॉलिंग से पूरी तरह से परहेज करना उचित नहीं है, क्योंकि पाइथन एक अलग तरीके से काम करता है। सी # कोड को संकलित करने से पहले, पूर्व-कंपाइलर में परिभाषित होता है। पायथन में, ऐसी कोई बात नहीं है।

यदि आप किसी कार्य वातावरण में डीबग करने के लिए कॉलिंग को पूरी तरह से हटाना चाहते हैं, तो मुझे लगता है कि निष्पादन से पहले कोड को वास्तव में बदलने का एकमात्र तरीका है। निष्पादन के पिछले एक स्क्रिप्ट के साथ आप डीबग लाइनों पर टिप्पणी/टिप्पणी कर सकते हैं।

कुछ इस तरह:

फ़ाइल logging.py

#Main module 
def log(): 
    print 'logging' 

def main(): 
    log() 
    print 'Hello' 
    log() 

फ़ाइल call_log.py

import re 
#To log or not to log, that's the question 
log = True 

#Change the loging 
with open('logging.py') as f: 
    new_data = [] 
    for line in f: 
     if not log and re.match(r'\s*log.*', line): 
     #Comment 
     line = '#' + line 
     if log and re.match(r'#\s*log.*', line): 
     #Uncomment 
     line = line[1:] 
     new_data.append(line) 

#Save file with adequate log level 
with open('logging.py', 'w') as f: 
    f.write(''.join(new_data)) 


#Call the module 
import logging 
logging.main() 
बेशक

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

-1

आप फ़ंक्शन कॉल नहीं छोड़ सकते हैं। हालांकि आप इसे खाली के रूप में फिर से परिभाषित कर सकते हैं, उदा। एक और लॉगिंग ऑब्जेक्ट बनाकर जो एक ही इंटरफेस प्रदान करता है, लेकिन खाली कार्यों के साथ।

लेकिन अब तक साफ दृष्टिकोण कम प्राथमिकता लॉग संदेशों की उपेक्षा करना (के रूप में आप का सुझाव दिया) है:

logging.root.setLevel(logging.CRITICAL) 
+1

मैंने खुद को स्पष्ट कर दिया है। मैं फंक्शन कॉल 'टिप्पणी आउट' करने के लिए एक सामान्य उद्देश्य पायथन हैक की तलाश में हूं। यही है, मैं 'टिप्पणी' कार्यों को भी बुलाया नहीं चाहता हूं। आपका सुझाव लॉगिंग.debug() पर फ़ंक्शन कॉल को समाप्त नहीं करता है। समारोह बुलाया जाता है, और कुछ प्रसंस्करण करता है। यही वह है जिसे मैं –

+0

से बचना चाहता हूं, आपने स्वयं को स्पष्ट कर दिया है, लेकिन मुझे नहीं लगता कि यह आपके लिए जो कुछ भी मांगे जाने के लिए पाइथोनिक है। – user238424

0

इससे पहले कि आप ऐसा करते हैं, आप की पुष्टि है कि प्रवेश वास्तव में एक पर्याप्त राशि ले जा रहा है प्रोफाइल है समय की? आप पाते हैं कि आप सहेजने से कॉल को हटाने का प्रयास करने में अधिक समय व्यतीत करते हैं।

इसके बाद, आप Psyco की तरह कुछ करने की कोशिश की है? यदि आपके पास चीजें सेट हो गई हैं तो लॉगिंग अक्षम कर दी गई है, तो साइको लॉगिंग फ़ंक्शन को कॉल करने के अधिकांश ओवरहेड को ऑप्टिमाइज़ करने में सक्षम हो सकता है, यह देखते हुए कि यह हमेशा बिना किसी कार्रवाई के वापस आ जाएगा।

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

+0

मैंने खुद को स्पष्ट नहीं किया है। मैंने एक उदाहरण के रूप में लॉगिंग मॉड्यूल और प्रदर्शन का उपयोग किया। कार्यों को टिप्पणी करने के लिए अन्य कारण हैं, उदाहरण के लिए, कोड –

1

ठीक है, आप हमेशा अपनी खुद की सरल पूर्वप्रक्रमक कि काम कर देता है लागू कर सकते हैं। या, इससे भी बेहतर, आप पहले से मौजूद एक का उपयोग कर सकते हैं। http://code.google.com/p/preprocess/

+0

से किसी सुविधा को समाप्त करते समय http://code.google.com/p/pypreprocessor/ भी है। –

2

कहो हालांकि मुझे लगता है कि सवाल पूरी तरह से स्पष्ट और वैध है (कई प्रतिक्रियाओं है कि अन्यथा सुझाव है के होते हुए भी), संक्षिप्त उत्तर "क्या इस के लिए अजगर में कोई समर्थन है" है।

केवल संभावित preprocessor suggestion के अलावा अन्य समाधान कुछ bytecode hacking उपयोग करने के लिए किया जाएगा। मैं कल्पना भी करने के लिए कि यह कैसे उच्च स्तरीय एपीआई के मामले में काम करना चाहिए शुरू नहीं होगा, लेकिन एक निम्न स्तर पर आप निर्देशों और फिर से लिख उन्हें खत्म करने के लिए की विशेष दृश्यों के लिए कोड वस्तुओं की जांच कल्पना कर सकता।

उदाहरण के लिए, निम्नलिखित दो कार्यों को देखो:

>>> def func(): 
... if debug: # analogous to if __debug__: 
...  foo 
>>> dis.dis(func) 
    2   0 LOAD_GLOBAL    0 (debug) 
       3 JUMP_IF_FALSE   8 (to 14) 
       6 POP_TOP 

    3   7 LOAD_GLOBAL    1 (foo) 
      10 POP_TOP 
      11 JUMP_FORWARD    1 (to 15) 
     >> 14 POP_TOP 
     >> 15 LOAD_CONST    0 (None) 
      18 RETURN_VALUE 

यहाँ आप debug की LOAD_GLOBAL के लिए स्कैन कर सकता है, और यह और सब कुछ JUMP_IF_FALSE लक्ष्य करने के लिए खत्म करने।

यह एक और अधिक परंपरागत सी शैली डिबग() फ़ंक्शन हो जाता है कि अच्छी तरह से एक पूर्वप्रक्रमक द्वारा नामोनिशान है:

>>> def func2(): 
... debug('bar', baz) 
>>> dis.dis(func2) 
    2   0 LOAD_GLOBAL    0 (debug) 
       3 LOAD_CONST    1 ('bar') 
       6 LOAD_GLOBAL    1 (baz) 
       9 CALL_FUNCTION   2 
      12 POP_TOP 
      13 LOAD_CONST    0 (None) 
      16 RETURN_VALUE 

यहाँ आप debug की LOAD_GLOBAL के लिए देखो और इसी CALL_FUNCTION अप करने के लिए सब कुछ पोंछा करती थी।

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

0

एक समारोह है कि कुछ नहीं करता है, यानी परिभाषित

def nuzzing(*args, **kwargs): pass 

तो बस सभी कार्यों आप चाहते हैं अपने कार्य के साथ से छुटकारा पाने के, ओवरलोड

logging.debug = nuzzing 
+0

मेरे मूल प्रश्न में इस समाधान का एक प्रकार शामिल है –

+0

हाँ, लेकिन आपके प्लेसहोल्डर फ़ंक्शन को दोबारा कॉल करने के लिए, आप तत्काल खराबता के लिए दरवाजा खोल रहे हैं (अधिकतम कॉल गहराई ढेर पार हो गया है)। हाल ही में cpython संकलक किसी भी फ़ंक्शन को कम करने के लिए पर्याप्त चालाक है जो किसी भी तरह से किसी भी तरह से गुजरता है, इसलिए किसी भी कॉल को प्रभावी रूप से टिप्पणी की जाती है। मुझे कल्पना नहीं है कि आपको एक बेहतर समाधान मिल जाएगा। – richo

0

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

मैं इसका उपयोग तब करता हूं जब मैं उत्पादन वातावरण में नया कोड तैनात करता हूं, जब बहुत सारे लॉगिंग स्टेटमेंट्स होते हैं जिन्हें मुझे उत्पादन सेटिंग में आवश्यकता नहीं होती है और वे प्रदर्शन को प्रभावित कर रहे हैं।

आप स्क्रिप्ट पा सकते हैं: http://dound.com/2010/02/python-logging-performance/

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