How to write verbose scripts

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven D'Aprano

    How to write verbose scripts

    I find myself writing command line tools in Python where I wish to
    include "verbose" output to stdout.

    I start with a helper function:


    def print_(obj, level=0):
    if _verbosity >= level:
    print obj


    And then I end up with functions or methods looking like this:


    def parrot(x)
    print_("precond ition", level=2)
    do_something()
    print_("status is good...", level=1)
    print_("parrot is squawking strongly now", level=2)
    do_something_el se()
    print_("squawk squawk squawk", level=3)
    do_more()
    print_("postcon dition", level=1)
    return something


    That often means that my functions end up with more message printing code
    than actual code. The whole thing seems messy and hard to manage for all
    but the smallest scripts.

    Worst of all, sometimes the messages I wish to print may be expensive to
    compute, and I don't want to waste time computing them if they aren't
    going to be printed because the verbosity is too low. But nor do I wish
    to fill my code with this:

    if _verbosity >= 3:
    x = calculate_compl icated_thing()
    print_(x, level=3)



    Is there a better way of doing this than the way I am going about it?



    --
    Steven
  • Joe Riopel

    #2
    Re: How to write verbose scripts

    On Tue, Sep 2, 2008 at 12:55 PM, Steven D'Aprano
    <steve@remove-this-cybersource.com .auwrote:
    Is there a better way of doing this than the way I am going about it?
    Would the logging module help, and just print the output to the stdout
    (or a file) instead?

    Comment

    • Mensanator

      #3
      Re: How to write verbose scripts

      On Sep 2, 11:55 am, Steven D'Aprano <st...@REMOVE-THIS-
      cybersource.com .auwrote:
      I find myself writing command line tools in Python where I wish to
      include "verbose" output to stdout.
      >
      I start with a helper function:
      >
      def print_(obj, level=0):
      if _verbosity >= level:
      print obj
      >
      And then I end up with functions or methods looking like this:
      >
      def parrot(x)
      print_("precond ition", level=2)
      do_something()
      print_("status is good...", level=1)
      print_("parrot is squawking strongly now", level=2)
      do_something_el se()
      print_("squawk squawk squawk", level=3)
      do_more()
      print_("postcon dition", level=1)
      return something
      >
      That often means that my functions end up with more message printing code
      than actual code. The whole thing seems messy and hard to manage for all
      but the smallest scripts.
      >
      Worst of all, sometimes the messages I wish to print may be expensive to
      compute, and I don't want to waste time computing them if they aren't
      going to be printed because the verbosity is too low. But nor do I wish
      to fill my code with this:
      >
      if _verbosity >= 3:
      x = calculate_compl icated_thing()
      print_(x, level=3)
      >
      Is there a better way of doing this than the way I am going about it?
      I do something like this, although I don't know if it would
      be an improvement.

      def collatz(a,p):
      """ 3x+1 sequencer, no loop detection

      collatz(a,p)
      a: starting value
      p: print options (binary)
      bit 0 print even numbers (turns off power division)
      bit 1 print odd numbers
      bit 2 print debug (if any)
      returns: CollatzSequence Parameters [R1count, R2count]
      """
      ONE = gmpy.mpz(1)
      TWO = gmpy.mpz(2)
      TWE = gmpy.mpz(3)
      a = gmpy.mpz(a)
      t = 0
      u = 0
      done = 0

      if (p & 1)==1:
      print_evens = True
      else:
      print_evens = False
      if (p & 2)==2:
      print_odds = True
      else:
      print_odds = False
      if (p & 4)==4:
      print_debug = True
      else:
      print_debug = False

      while done==0:
      f = gmpy.scan1(a,0) # locate LS 1-bit
      if f>0: # it's even
      if print_evens:
      print a,
      a = a >1 # no power division
      u += 1
      else:
      a = a >f # power division
      u += f
      else:
      if print_odds:
      print a,
      if a==1:
      done = 1
      seq_end = t + u
      else:
      a = a*TWE + ONE
      t += 1
      return [u,t]


      >
      --
      Steven

      Comment

      • Diez B. Roggisch

        #4
        Re: How to write verbose scripts

        Steven D'Aprano schrieb:
        I find myself writing command line tools in Python where I wish to
        include "verbose" output to stdout.
        >
        I start with a helper function:
        >
        >
        def print_(obj, level=0):
        if _verbosity >= level:
        print obj
        >
        >
        And then I end up with functions or methods looking like this:
        >
        >
        def parrot(x)
        print_("precond ition", level=2)
        do_something()
        print_("status is good...", level=1)
        print_("parrot is squawking strongly now", level=2)
        do_something_el se()
        print_("squawk squawk squawk", level=3)
        do_more()
        print_("postcon dition", level=1)
        return something
        >
        >
        That often means that my functions end up with more message printing code
        than actual code. The whole thing seems messy and hard to manage for all
        but the smallest scripts.
        >
        Worst of all, sometimes the messages I wish to print may be expensive to
        compute, and I don't want to waste time computing them if they aren't
        going to be printed because the verbosity is too low. But nor do I wish
        to fill my code with this:
        >
        if _verbosity >= 3:
        x = calculate_compl icated_thing()
        print_(x, level=3)
        >
        >
        >
        Is there a better way of doing this than the way I am going about it?
        I use the logging-module.

        Regarding the expensive computations: maysomething like this help:

        class DeferredToStrin g(object):

        def __init__(self, func):
        self.func = func

        def __repr__(self):
        return repr(self.func( ))

        def __str__(self):
        return str(self.func() )



        dts = DeferredToStrin g

        Because then you can do

        logger.debug("S ome text for an: %r", dts(lambda: long_computatio n()))

        Because AFAIK the string is only interpolated if the logging level is
        actually put out.

        Diez

        Comment

        • MRAB

          #5
          Re: How to write verbose scripts

          On Sep 2, 5:55 pm, Steven D'Aprano <st...@REMOVE-THIS-
          cybersource.com .auwrote:
          I find myself writing command line tools in Python where I wish to
          include "verbose" output to stdout.
          >
          I start with a helper function:
          >
          def print_(obj, level=0):
              if _verbosity >= level:
                  print obj
          >
          And then I end up with functions or methods looking like this:
          >
          def parrot(x)
              print_("precond ition", level=2)
              do_something()
              print_("status is good...", level=1)
              print_("parrot is squawking strongly now", level=2)
              do_something_el se()
              print_("squawk squawk squawk", level=3)
              do_more()
              print_("postcon dition", level=1)
              return something
          >
          That often means that my functions end up with more message printing code
          than actual code. The whole thing seems messy and hard to manage for all
          but the smallest scripts.
          >
          Worst of all, sometimes the messages I wish to print may be expensive to
          compute, and I don't want to waste time computing them if they aren't
          going to be printed because the verbosity is too low. But nor do I wish
          to fill my code with this:
          >
          if _verbosity >= 3:
              x = calculate_compl icated_thing()
              print_(x, level=3)
          >
          Is there a better way of doing this than the way I am going about it?
          >
          How about:

          def print_(obj, level=0):
          if _verbosity >= level:
          if callable(obj):
          obj = obj()
          print obj

          so that you could then use:

          print_("precond ition", level=2)

          and:

          print_(calculat e_complicated_t hing, level=3)

          or:

          print_(lambda: calculate_compl icated_thing(ar gument), level=3)

          Comment

          • John Machin

            #6
            Re: How to write verbose scripts

            On Sep 3, 3:52 am, Mensanator <mensana...@aol .comwrote:
            On Sep 2, 11:55 am, Steven D'Aprano <st...@REMOVE-THIS-
            >
            if (p & 1)==1:
            print_evens = True
            else:
            print_evens = False
            if (p & 2)==2:
            print_odds = True
            else:
            print_odds = False
            if (p & 4)==4:
            print_debug = True
            else:
            print_debug = False
            No, no, no, you've taken "How to write verbose scripts" rather too
            literally; try this:

            print_evens = p & 1
            print_odds = p & 2
            print_debug = p & 4

            Comment

            • Mensanator

              #7
              Re: How to write verbose scripts

              On Sep 2, 4:14 pm, John Machin <sjmac...@lexic on.netwrote:
              On Sep 3, 3:52 am, Mensanator <mensana...@aol .comwrote:
              >
              On Sep 2, 11:55 am, Steven D'Aprano <st...@REMOVE-THIS-
              >
              if (p & 1)==1:
              print_evens = True
              else:
              print_evens = False
              if (p & 2)==2:
              print_odds = True
              else:
              print_odds = False
              if (p & 4)==4:
              print_debug = True
              else:
              print_debug = False
              >
              No, no, no, you've taken "How to write verbose scripts" rather too
              literally; try this:
              >
              print_evens = p & 1
              print_odds = p & 2
              print_debug = p & 4
              Thanks for that. Luckily, the code only does that once per call.

              Comment

              • Bruno Desthuilliers

                #8
                Re: How to write verbose scripts

                John Machin a écrit :
                On Sep 3, 3:52 am, Mensanator <mensana...@aol .comwrote:
                >On Sep 2, 11:55 am, Steven D'Aprano <st...@REMOVE-THIS-
                >>
                > if (p & 1)==1:
                > print_evens = True
                > else:
                > print_evens = False
                > if (p & 2)==2:
                > print_odds = True
                > else:
                > print_odds = False
                > if (p & 4)==4:
                > print_debug = True
                > else:
                > print_debug = False
                >
                No, no, no, you've taken "How to write verbose scripts" rather too
                literally;
                KEYBOARD !

                Comment

                • Uwe Schmitt

                  #9
                  Re: How to write verbose scripts

                  On 2 Sep., 18:55, Steven D'Aprano <st...@REMOVE-THIS-
                  cybersource.com .auwrote:
                  I find myself writing command line tools in Python where I wish to
                  include "verbose" output to stdout.
                  >
                  I start with a helper function:
                  >
                  def print_(obj, level=0):
                      if _verbosity >= level:
                          print obj
                  >
                  And then I end up with functions or methods looking like this:
                  >
                  def parrot(x)
                      print_("precond ition", level=2)
                      do_something()
                      print_("status is good...", level=1)
                      print_("parrot is squawking strongly now", level=2)
                      do_something_el se()
                      print_("squawk squawk squawk", level=3)
                      do_more()
                      print_("postcon dition", level=1)
                      return something
                  >
                  That often means that my functions end up with more message printing code
                  than actual code. The whole thing seems messy and hard to manage for all
                  but the smallest scripts.
                  >
                  Worst of all, sometimes the messages I wish to print may be expensive to
                  compute, and I don't want to waste time computing them if they aren't
                  going to be printed because the verbosity is too low. But nor do I wish
                  to fill my code with this:
                  >
                  if _verbosity >= 3:
                      x = calculate_compl icated_thing()
                      print_(x, level=3)
                  >
                  Is there a better way of doing this than the way I am going about it?
                  >
                  --
                  Steven
                  You can save some code if you use function decorators for logging
                  input and output values of
                  functions.
                  So write lots of functions containing one statement and your problem
                  is solved ;-)

                  Greetings, Uwe

                  Comment

                  • Steven D'Aprano

                    #10
                    Re: How to write verbose scripts

                    On Tue, 02 Sep 2008 13:07:33 -0400, Joe Riopel wrote:
                    On Tue, Sep 2, 2008 at 12:55 PM, Steven D'Aprano
                    <steve@remove-this-cybersource.com .auwrote:
                    >Is there a better way of doing this than the way I am going about it?
                    >
                    Would the logging module help, and just print the output to the stdout
                    (or a file) instead?
                    Thank you to everyone who answered.

                    As I feared, it seems that there's no really simple way of dealing with
                    arbitrary messages at arbitrary parts of my code.

                    I'm currently playing around with a few ideas, one of which is a
                    decorator to print information about function calls. However, what I'd
                    like to avoid is having to explicitly call the decorator on every method.
                    I guess that there's metaclass trickery I can play. Does anyone have any
                    pointers on how I can apply a decorator to every method in a class
                    automatically?



                    --
                    Steven

                    Comment

                    • Ben Finney

                      #11
                      Re: How to write verbose scripts

                      Steven D'Aprano <steve@REMOVE-THIS-cybersource.com .auwrites:
                      On Tue, 02 Sep 2008 13:07:33 -0400, Joe Riopel wrote:
                      >
                      On Tue, Sep 2, 2008 at 12:55 PM, Steven D'Aprano
                      <steve@remove-this-cybersource.com .auwrote:
                      Is there a better way of doing this than the way I am going about it?
                      Would the logging module help, and just print the output to the stdout
                      (or a file) instead?
                      >
                      Thank you to everyone who answered.
                      >
                      As I feared, it seems that there's no really simple way of dealing with
                      arbitrary messages at arbitrary parts of my code.
                      I would think the 'logging' module *is* the simple way to do this. At
                      least, it's as simple as it could be without leading to massive
                      re-visiting of the "arbitrary parts of one's code" when later desiring
                      to change the way the messages are handled.

                      --
                      \ “We must become the change we want to see.” —Mahatma Gandhi |
                      `\ |
                      _o__) |
                      Ben Finney

                      Comment

                      • Lie

                        #12
                        Re: How to write verbose scripts

                        On Sep 3, 6:31 pm, Uwe Schmitt <rocksportroc.. .@googlemail.co mwrote:
                        On 2 Sep., 18:55, Steven D'Aprano <st...@REMOVE-THIS-
                        >
                        >
                        >
                        cybersource.com .auwrote:
                        I find myself writing command line tools in Python where I wish to
                        include "verbose" output to stdout.
                        >
                        I start with a helper function:
                        >
                        def print_(obj, level=0):
                            if _verbosity >= level:
                                print obj
                        >
                        And then I end up with functions or methods looking like this:
                        >
                        def parrot(x)
                            print_("precond ition", level=2)
                            do_something()
                            print_("status is good...", level=1)
                            print_("parrot is squawking strongly now", level=2)
                            do_something_el se()
                            print_("squawk squawk squawk", level=3)
                            do_more()
                            print_("postcon dition", level=1)
                            return something
                        >
                        That often means that my functions end up with more message printing code
                        than actual code. The whole thing seems messy and hard to manage for all
                        but the smallest scripts.
                        >
                        Worst of all, sometimes the messages I wish to print may be expensive to
                        compute, and I don't want to waste time computing them if they aren't
                        going to be printed because the verbosity is too low. But nor do I wish
                        to fill my code with this:
                        >
                        if _verbosity >= 3:
                            x = calculate_compl icated_thing()
                            print_(x, level=3)
                        >
                        Is there a better way of doing this than the way I am going about it?
                        >
                        --
                        Steven
                        >
                        You can save some code if you use function decorators for logging
                        input and output values of
                        functions.
                        So write lots of functions containing one statement and your problem
                        is solved ;-)
                        >
                        Greetings, Uwe
                        That would be perfect if python is a fully functional language (read
                        that as: purely functional language). Functional language dictates no
                        side effects, so logging input and output of functions is pretty much
                        everything needed to do debugging (which is the main reason for having
                        verbose mode). It would still be feasible, though, if you keep
                        yourself from using functions with side-effects (or use as few of them
                        as possible).

                        Bjorn Lindqvist says:
                        One big downside with that approach is that it becomes much harder to
                        grep for the log message. Usually when I go through logs, I don't care
                        what exactly the message says, just that it is easily googleable (uses
                        some kind of identifying text) and that it is unique so I can know
                        exactly where it was emitted.
                        Actually, I'd prefer a log code (perhaps also as an option, to use -e
                        for showing up log code besides the log message). The log code would
                        be unique and referenced only once in the whole application (to nail
                        down who said what to a single point). The code would make a call to
                        the log printer with the log code (not the error string) and a few
                        arguments to be interpolated to the error string (taken from a
                        dictionary indexed by error code).

                        The downside is loss of inline documentation by the logging codes.

                        Comment

                        Working...