Hoe de uitvoering van de –verbose of de -v optie in een script?

Ik weet het --verbose of -v uit verschillende hulpprogramma ‘ s en ik zou graag om dit te implementeren in een aantal van mijn eigen scripts en tools.

Ik dacht van plaatsing:

if verbose:
    print ...

door mijn source code, zodat wanneer een gebruiker voor het doorgeven van de -v optie, de variabele verbose zal worden ingesteld op True en de tekst wordt afgedrukt.

Is dit de juiste aanpak of is er een meer algemene manier?

Bovendien: ik ben niet gevraagd naar een manier om de uitvoering van het parseren van argumenten. Dat ik weet hoe het is gedaan. Ik ben alleen geïnteresseerd in het bijzonder in de uitgebreide optie.

  • Waarom niet gebruik maken van de logging module en het instellen van de log-niveau INFO standaard, en FOUTOPSPORING wanneer –verbose wordt doorgegeven? Best niet te reimplement iets dat al beschikbaar is in de taal…
  • Ik ga akkoord, maar de logging module is behoorlijk pijnlijk.
InformationsquelleAutor Aufwind | 2011-05-12



9 Replies
  1. 93

    Mijn suggestie is om een functie te gebruiken. Maar in plaats van dat de if in de functie, die u misschien in de verleiding om te doen, doe het zo:

    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

    (Ja, kunt u een functie in een if verklaring, en het zal alleen maar gedefinieerd als de voorwaarde waar is!)

    Als je een Python 3, waar print is al een functie (of als je bereid bent om print als een functie in 2.x met from __future__ import print_function) is het zelfs nog eenvoudiger:

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

    Deze manier de functie is gedefinieerd als een do-nothing als verbose modus is uitgeschakeld (met behulp van een lambda), in plaats van voortdurend testen van de verbose vlag.

    Als de gebruiker kan wijzigen van het breedsprakigheid modus tijdens het uitvoeren van uw programma, zou dit de verkeerde benadering (je zou het if in de functie), maar omdat je nu met een commando-regel optie, hoeft u alleen maar te maken met het besluit eens.

    Je dan gebruik maken van bijvoorbeeld verboseprint("look at all my verbosity!", object(), 3) wanneer u wilt afdrukken van een “uitgebreide” bericht.

    • Nog beter, doe het dan als de print functie: Accepteren veel argumenten. Het kan worden geïmplementeerd als print(*args) in 3.x en als for arg in args: print arg, in 2.x. Het belangrijkste voordeel is dat het mengen van strijkers en dingen van andere typen in een bericht, zonder expliciete str oproepen/opmaak en koppelingen.
    • Ik hou van die idee, ik update mijn antwoord.
    • Wat is de komma gebruikt wordt om aan het einde van de print arg, lijn?
    • Dat is gemakkelijk bepaald voor jezelf experimenteel of door het controleren van de documentatie, maar het onderdrukt de lijn breken die normaal gesproken zouden worden afgedrukt.
    • De Python 3 print-functie neemt ook leverbaar trefwoord argument, dus om volledig te reproduceren van de functionaliteit van afdrukken: def verboseprint(*args, **kwargs): print(*args, **kwargs)
  2. 54

    Gebruik de logging module:

    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.")

    Al deze automatisch naar 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.

    Voor meer info, zie de Python-Docs en de tutorials.

    • Volgens de Python-Docs, hier, logging dient niet te worden gebruikt in gevallen waar u alleen verlangen om afdrukken in de normale uitvoering van het programma. Het ziet eruit als dat is wat het OP wil.
    • Dit lijkt goed voor het fundamentele probleem, maar veel *nix opdrachten ook ondersteuning voor meerdere niveaus van breedsprakigheid (-v -v -v, etc.), die zou kunnen krijgen rommelig op deze manier.
  3. 11

    Gebouw en vereenvoudiging @kindall ‘ s antwoord, hier is wat ik meestal gebruik:

    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()

    Dit geeft dan het volgende gebruik in uw script:

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

    En het script kan worden genoemd:

    % 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

    Een paar opmerkingen:

    1. Uw eerste argument is uw fout niveau, en de tweede is uw boodschap. Het is het magische aantal van 3 dat stelt de bovengrens voor uw loggen, maar ik accepteer dat als een compromis voor eenvoud.
    2. Als u wilt v_print om te werken in uw programma, moet u de junk met de wereld. Het is niet leuk, maar ik daag iemand een betere manier vinden.
    • Waarom ga je niet gebruik maken van de logging module voor INFO en WAARSCHUWEN? Dat wordt importeren wanneer -v wordt gebruikt. In uw huidige oplossing, alles is gedumpt naar stdout in plaats van stderr. En: u normaal gesproken willen relais elke fout aan de gebruiker, denk je niet?
    • Ja, dat is een reële punt. Registratie heeft een aantal cognitieve overhead die ik probeerde te vermijden, maar het is waarschijnlijk de “juiste” dingen te doen. Het is gewoon ergerde me in het verleden…
  4. 9

    Wat ik doe in mijn scripts is te controleren tijdens runtime als de ‘uitgebreide’ optie is ingesteld, en stel mijn niveau van logboekregistratie voor foutopsporing. Als het niet is ingesteld, stel ik het naar info. Op deze manier hoef je niet ‘als uitgebreide’ checks over je code.

  5. 2

    Het kan schoner als je een functie, zeg genoemd vprint, dat controleert of de uitgebreide vlag voor je. Dan moet je gewoon bellen met je eigen vprint functie elke plek die u wilt optioneel breedsprakigheid.

  6. 1

    @kindall de oplossing werkt niet met mijn Python versie 3.5. @stijlen correct stelt in zijn reactie dat de reden is de extra optionele trefwoorden argument. Vandaar mijn iets verfijnde versie van Python 3 ziet er zo uit:

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

    Kan er een globale variabele, waarschijnlijk met argparse van sys.argv, dat staat voor de vraag of het programma moet worden uitgebreid of niet.
    Vervolgens een binnenhuisarchitect kan worden geschreven als ‘detailniveau’ was, dan is de standaard ingang zou worden omgeleid naar de null-apparaat als u de functie uitvoert:

    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")

    Dit antwoord is geïnspireerd door deze code; eigenlijk was ik van plan om gewoon te gebruiken als een module in mijn programma, maar ik heb fouten ik kon het niet begrijpen, dus ik paste een deel van het.

    Het nadeel van deze oplossing is dat verbosity is binair, in tegenstelling tot logging, die zorgt voor een fijnere afstemming van hoe uitgebreid het programma kan worden.
    Ook alle print oproepen worden doorgeschakeld, die mogelijk ongewenst voor.

  8. 0

    Wat ik nodig heb is een functie die de prenten van een object (obj), maar alleen als globale variabele verbose waar is, anders is het niets doet.

    Ik wil in staat zijn om de globale parameter “verbose” op elk moment. De eenvoud en de leesbaarheid zijn voor mij van het grootste belang. Dus ik zou gaan als de volgende lijnen geven:

    [email protected]:~$ 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')
    >>> 

    Globale variabele “verbose” kan worden ingesteld in de parameter lijst, ook.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *