स्क्रिप्ट में theverbose या -v विकल्प कैसे लागू करें?


94

मैं --verboseया -vकई उपकरणों से जानता हूं और मैं इसे अपनी कुछ स्क्रिप्ट्स और टूल्स में लागू करना चाहता हूं।

मैंने सोचा:

if verbose:
    print ...

मेरे स्रोत कोड के माध्यम से, ताकि यदि कोई उपयोगकर्ता -vविकल्प पास करता है, तो चर verboseसेट हो जाएगा Trueऔर पाठ मुद्रित हो जाएगा।

क्या यह सही दृष्टिकोण है या कोई अधिक सामान्य तरीका है?

जोड़: मैं तर्कों को लागू करने का तरीका नहीं पूछ रहा हूं। कि मुझे पता है कि यह कैसे किया जाता है। मुझे केवल विशेष रूप से क्रिया विकल्प में दिलचस्पी है।


9
लॉगिंग मॉड्यूल का उपयोग क्यों न करें और डिफ़ॉल्ट रूप से लॉग स्तर INFO सेट करें, और जब --verbose पारित हो जाता है? सबसे अच्छी बात यह है कि पहले से ही भाषा में उपलब्ध किसी भी चीज़ को फिर से लागू न करें ...
टिम

3
@ टिम, मैं सहमत हूं, लेकिन लॉगिंग मॉड्यूल बहुत दर्दनाक है।
mlissner

जवाबों:


106

मेरा सुझाव एक फ़ंक्शन का उपयोग करना है। लेकिन ifफंक्शन में डालने के बजाय , जिसे आप करने के लिए लुभा सकते हैं, इसे इस तरह से करें:

if verbose:
    def verboseprint(*args):
        # Print each argument separately so caller doesn't need to
        # stuff everything to be printed into a single string
        for arg in args:
           print arg,
        print
else:   
    verboseprint = lambda *a: None      # do-nothing function

(हां, आप किसी फ़ंक्शन को a में परिभाषित कर सकते हैं if कथन , और यह केवल तभी परिभाषित होगा जब स्थिति सही हो!)

यदि आप पायथन 3 का उपयोग कर रहे हैं, जहां printपहले से ही एक फ़ंक्शन है (या यदि आप print2.x का उपयोग करके फ़ंक्शन के रूप में उपयोग करने के लिए तैयार हैं from __future__ import print_function) तो यह बहुत आसान है:

verboseprint = print if verbose else lambda *a, **k: None

इस तरह, फ़ंक्शन को क्रिया के रूप में परिभाषित किया जाता है, अगर वर्बोज़ मोड बंद है (लैम्बडा का उपयोग करके), लगातार परीक्षण के बजाय verbose

यदि उपयोगकर्ता रन के दौरान वर्बोसिटी मोड को बदल सकता है आपके प्रोग्राम के , तो यह गलत दृष्टिकोण होगा (आपको ifफ़ंक्शन में इसकी आवश्यकता होगी ), लेकिन जब से आप इसे कमांड-लाइन ध्वज के साथ सेट कर रहे हैं, तो आपको केवल इसकी आवश्यकता है एक बार निर्णय लें।

आप तब उदाहरण के लिए उपयोग करते हैं verboseprint("look at all my verbosity!", object(), 3)जब भी आप एक "क्रिया" संदेश मुद्रित करना चाहते हैं।


1
इससे भी बेहतर, इसे printफ़ंक्शन के रूप में करें: कई तर्कों को स्वीकार करें। इसे print(*args)3.x के रूप for arg in args: print arg,में और 2.x में लागू किया जा सकता है। मुख्य लाभ यह है कि यह स्पष्ट संदेश str/ फ़ॉर्मेटिंग और कॉन्सेप्टेशन के बिना एक संदेश में तार और अन्य प्रकार की चीजों को मिलाने की अनुमति देता है ।

print arg,लाइन के अंत में कॉमा का उपयोग किस लिए किया जाता है ?
सैमके

यह आसानी से किसी के स्वयं के लिए निर्धारित किया जाता है या दस्तावेज़ीकरण की जांच करके, लेकिन यह उस लाइन ब्रेक को दबा देता है जो सामान्य रूप से मुद्रित होता है।
kindall

5
अजगर 3 प्रिंट फ़ंक्शन वैकल्पिक कीवर्ड तर्क भी लेता है, इसलिए प्रिंट की कार्यक्षमता को पूरी तरह से पुन: पेश करने के लिए:def verboseprint(*args, **kwargs): print(*args, **kwargs)
lstyls

61

loggingमॉड्यूल का उपयोग करें :

import logging as log

args = p.parse_args()
if args.verbose:
    log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG)
    log.info("Verbose output.")
else:
    log.basicConfig(format="%(levelname)s: %(message)s")

log.info("This should be verbose.")
log.warning("This is a warning.")
log.error("This is an error.")

ये सभी स्वचालित रूप से यहां जाते हैं stderr:

% python myprogram.py
WARNING: This is a warning.
ERROR: This is an error.

% python myprogram.py -v
INFO: Verbose output.
INFO: This should be verbose.
WARNING: This is a warning.
ERROR: This is an error.

अधिक जानकारी के लिए, पायथन डॉक्स और ट्यूटोरियल देखें


8
यहां पाइथन डॉक्स के अनुसार , लॉगिंग का उपयोग उन मामलों में नहीं किया जाना चाहिए, जहां आपको केवल प्रोग्राम के सामान्य निष्पादन में आउटपुट प्रिंट करने की आवश्यकता होती है। ऐसा लगता है कि ओपी क्या चाहता है।
सैंडीवैलर

1
यह मूल समस्या के लिए ठीक लगता है, लेकिन कई * निक्स कमांड वर्बोसिटी (-v -v -v, आदि) के कई स्तरों का भी समर्थन करते हैं, जो इस तरह गड़बड़ हो सकता है।
टेक्स्टकेक

12

@ किंडल के उत्तर का निर्माण और सरलीकरण, यहां मैं आमतौर पर उपयोग करता हूं:

v_print = None
def main()
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbosity', action="count", 
                        help="increase output verbosity (e.g., -vv is more than -v)")

    args = parser.parse_args()

    if args.verbosity:
        def _v_print(*verb_args):
            if verb_args[0] > (3 - args.verbosity):
                print verb_args[1]  
    else:
        _v_print = lambda *a: None  # do-nothing function

    global v_print
    v_print = _v_print

if __name__ == '__main__':
    main()

यह तब आपकी स्क्रिप्ट में निम्नलिखित उपयोग प्रदान करता है:

v_print(1, "INFO message")
v_print(2, "WARN message")
v_print(3, "ERROR message")

और आपकी स्क्रिप्ट को इस तरह कहा जा सकता है:

% python verbose-tester.py -v
ERROR message

% python verbose=tester.py -vv
WARN message
ERROR message

% python verbose-tester.py -vvv
INFO message
WARN message
ERROR message

एक दो नोट:

  1. आपका पहला तर्क आपकी त्रुटि स्तर है, और दूसरा आपका संदेश है। इसका जादू नंबर है3 जो आपके लॉगिंग के लिए ऊपरी सीमा निर्धारित करता है, लेकिन मैं इसे सादगी के लिए समझौता मानता हूं।
  2. यदि आप v_printअपने पूरे कार्यक्रम में काम करना चाहते हैं , तो आपको ग्लोबल के साथ जंक करना होगा। यह कोई मज़ा नहीं है, लेकिन मैं किसी को बेहतर तरीका खोजने के लिए चुनौती देता हूं।

1
आप INFO और WARN के लिए लॉगिंग मॉड्यूल का उपयोग क्यों नहीं करते हैं? इसका -vउपयोग होने पर इसे आयात किया जाता है। आपके वर्तमान समाधान में सबकुछ stderr के बजाय stdout में डंप किया जाता है। और: आप सामान्य रूप से उपयोगकर्ता को हर त्रुटि को रिले करना चाहते हैं, है न?
प्रोफैट्स

2
हाँ, यह एक उचित बिंदु है। लॉगिंग में कुछ संज्ञानात्मक ओवरहेड है जो मैं बचने की कोशिश कर रहा था, लेकिन यह शायद "सही" करने की बात है। यह मुझे अतीत में परेशान कर रहा है ...
mlissner

9

अगर मैं अपनी स्क्रिप्ट्स में रनटाइम पर जाँच करता हूँ अगर 'वर्बोज़' विकल्प सेट है, और फिर अपने लॉगिंग स्तर को डीबग करने के लिए सेट करें। यदि यह सेट नहीं है, तो मैंने इसे जानकारी पर सेट कर दिया है। इस तरह आपके पास ver यदि क्रिया ’नहीं है, तो आपके कोड पर सभी की जाँच होती है।


2

यदि आपके पास कोई फ़ंक्शन है, तो यह साफ हो सकता है, कहते हैं vprint, जो आपके लिए क्रिया ध्वज की जांच करता है। फिर आप बस अपने स्वयं के vprintफ़ंक्शन को किसी भी स्थान पर कॉल करें जिसे आप वैकल्पिक वर्बोसिटी चाहते हैं।


2

मैंने मेरा एक प्रोजेक्ट के लिए virtualenv से लॉगिंग कोड चुरा लिया है । में देखो के देखने के लिए कि यह कैसे प्रारंभ कर रहा है। कोड के साथ छिड़का जाता है , , , और पसंद है। कौन सा तरीकों वास्तव में फेंकना उत्पादन से है कि क्या virtualenv के साथ लागू किया गया था निर्धारित किया जाता है , , , या ।main()virtualenv.pylogger.notify()logger.info()logger.warn()-v-vv-vvv-q


2

@ किंडल का समाधान मेरे पायथन संस्करण 3.5 के साथ काम नहीं करता है। @ स्टाइल्स अपनी टिप्पणी में सही बताते हैं कि इसका कारण अतिरिक्त वैकल्पिक कीवर्ड तर्क है। इसलिए पायथन 3 के लिए मेरा थोड़ा परिष्कृत संस्करण इस तरह दिखता है:

if VERBOSE:
    def verboseprint(*args, **kwargs):
        print(*args, **kwargs)
else:
    verboseprint = lambda *a, **k: None # do-nothing function

1

एक वैश्विक चर हो सकता है, जिसमें argparseसे निश्चित रूप से सेट किया गया है sys.argv, जो इस बात के लिए है कि कार्यक्रम को क्रियात्मक होना चाहिए या नहीं। तब एक डेकोरेटर को ऐसा लिखा जा सकता है कि अगर वर्बोसिटी चालू थी, तो मानक इनपुट को शून्य डिवाइस में तब तक डायवर्ट किया जाएगा, जब तक कि फ़ंक्शन चलना था:

import os
from contextlib import redirect_stdout
verbose = False

def louder(f):
    def loud_f(*args, **kwargs):
        if not verbose:
            with open(os.devnull, 'w') as void:
                with redirect_stdout(void):
                    return f(*args, **kwargs)
        return f(*args, **kwargs)
    return loud_f

@louder
def foo(s):
    print(s*3)

foo("bar")

यह उत्तर इस कोड से प्रेरित है ; वास्तव में, मैं इसे अपने कार्यक्रम में एक मॉड्यूल के रूप में उपयोग करने जा रहा था, लेकिन मुझे ऐसी त्रुटियां मिलीं जिन्हें मैं समझ नहीं सका, इसलिए मैंने इसके एक हिस्से को अनुकूलित किया।

इस समाधान का नकारात्मक पक्ष यह है कि वर्बोसिटी द्विआधारी है, इसके विपरीत logging, जो कार्यक्रम को कैसे क्रिया कर सकता है , इसके बारे में महीन जानकारी देता है। इसके अलावा, सभी print कॉल को डायवर्ट किया जाता है, जो कि अवांछित हो सकता है।


0

मुझे एक फ़ंक्शन की आवश्यकता है जो किसी ऑब्जेक्ट (obj) को प्रिंट करता है, लेकिन केवल अगर वैश्विक चर क्रिया सत्य है, तो यह कुछ भी नहीं करता है।

मैं किसी भी समय वैश्विक पैरामीटर "क्रिया" को बदलने में सक्षम होना चाहता हूं। मेरे लिए सरलता और पठनीयता सर्वोपरि है। इसलिए मैं निम्नलिखित पंक्तियों को इंगित करता हूं:

ak@HP2000:~$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> verbose = True
>>> def vprint(obj):
...     if verbose:
...         print(obj)
...     return
... 
>>> vprint('Norm and I')
Norm and I
>>> verbose = False
>>> vprint('I and Norm')
>>> 

वैश्विक चर "वर्बोज़" को पैरामीटर सूची से भी सेट किया जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.