Python equivalent for C module

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Derek Martin

    Python equivalent for C module

    I'd like to know if it's possible to code something in Python which
    would be equivalent to the following C:

    [Assume bool is typedef'd to int, and TRUE and FALSE are #defined to 1
    and 0, respectively]

    ---- debug.c ----
    #include <stdio.h>

    bool DEBUG;

    void dprint(char *msg)
    {
    if (DEBUG){
    printf("DEBUG: %s", msg);
    }
    }

    ---- end of debug.c ----

    The idea being that all modules of the program would "import" this
    code via the header file:

    ---- debug.h ----
    extern bool DEBUG;
    void dprint(char *msg);
    ---- end of debug.h ----

    I'm specifically trying to avoid having to create a debug object and
    pass it around... All modules should have visibility into the state of
    whether DEBUG is turned on or off, and be able to use dprint(). Can
    Python do this?

    I tried creating debug.py as such:

    ---- debug.py ----
    DEBUG = True
    def dprint(msg):
    if DEBUG:
    print("DEBUG: %s" % msg)
    ---- end ----

    Then in the modules that wanted to use it, I did:

    from debug import DEBUG, dprint

    But I got some weird behavior. The imported copy of DEBUG is
    read-only; if you update it, the name DEBUG points to a different
    object which the other modules can't see. After doing some reading of
    the docs, this behavior is explained and understood (though obviously
    not what I want). It just occured to me that I might be able to get
    around that by using a setter function in the module itself... I'll
    try this later.

    The other weird behavior was, once I changed the value of DEBUG,
    dprint() started to behave oddly. No matter what I passed as an
    argument (and no matter what I set the value of DEBUG to be), it
    started printing the exact literal string:

    DEBUG: %s

    whenever it was called. It was as if the function couldn't see the
    parameter msg, which was passed via the call. Most unexpected, and
    definitely undesirable.

    --
    Derek D. Martin

    GPG Key ID: 0x81CFE75D


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.1 (GNU/Linux)

    iD8DBQFI/L2HdjdlQoHP510R AhK6AJ4sD23vaAl BxaCYFGlS9g6Uhh d1FACeJbkO
    kIDJ86K7S2+B5m0 uKKNoIlo=
    =5Uek
    -----END PGP SIGNATURE-----

  • Aaron Brady

    #2
    Re: Python equivalent for C module

    On Oct 20, 12:19 pm, Derek Martin <c...@pizzashac k.orgwrote:
    snip
    >
    I'm specifically trying to avoid having to create a debug object and
    pass it around... All modules should have visibility into the state of
    whether DEBUG is turned on or off, and be able to use dprint().  Can
    Python do this?
    >
    I tried creating debug.py as such:
    >
    ---- debug.py ----
    DEBUG = True
    def dprint(msg):
        if DEBUG:
            print("DEBUG: %s" % msg)
    ---- end ----
    >
    Then in the modules that wanted to use it, I did:
    >
    from debug import DEBUG, dprint
    >
    But I got some weird behavior.  The imported copy of DEBUG is
    read-only; if you update it, the name DEBUG points to a different
    object which the other modules can't see.  After doing some reading of
    the docs, this behavior is explained and understood (though obviously
    not what I want).  It just occured to me that I might be able to get
    around that by using a setter function in the module itself... I'll
    try this later.
    >
    The other weird behavior was, once I changed the value of DEBUG,
    dprint() started to behave oddly.  No matter what I passed as an
    argument (and no matter what I set the value of DEBUG to be), it
    started printing the exact literal string:
    >
    DEBUG: %s
    >
    whenever it was called.  It was as if the function couldn't see the
    parameter msg, which was passed via the call.  Most unexpected, and
    definitely undesirable.
    >
    It should work if you set the attribute of the module directly.

    (untested)
    import debug
    debug.DEBUG= True
    debug.DEBUG= False

    Your idea of a module getter/setter should work too.

    def set_debug( val ):
    global DEBUG
    DEBUG= val

    Can't help with the other problem. Simplify a little with just
    print( msg ).

    Comment

    • Ville M. Vainio

      #3
      Re: Python equivalent for C module

      Bruno Desthuilliers <bdesth.quelque chose@free.quel quepart.frwrite s:
      STDOUT is for *normal* program outputs. Debug informations,
      warnings, and all verbosity should go to STDERR.
      Actually, stderr is for errors, by convention. It's rather impolite to
      dump trivial debug info to stderr, which often "alerts" the user more
      than stdout.
      Also and FWIW, Python has a logging module in it's stdlib. Please
      use it instead of any half-backed squared-wheel homegrown solution.
      Unfortunately these square-wheeled homegrown solutions are easier to
      grok than the standard logging module. It seems to target more
      "serious" applications at the cost of feeling a bit too clunky for
      quick hack jobs.

      Comment

      • Derek Martin

        #4
        Re: Python equivalent for C module

        On Mon, Oct 20, 2008 at 07:29:16PM +0200, Bruno Desthuilliers wrote:
        This should have been:
        >
        fprintf(STDERR, "DEBUG: %s", msg);
        No, it shouldn't have. If I turn on debugging, I want the debug
        messages to go to stdout, so that they can be captured along with the
        output (of which there is almost none anyway) to clearly indicate when
        they happened.
        STDOUT is for *normal* program outputs. Debug informations, warnings,
        and all verbosity should go to STDERR.
        That's your opinion, and I disagree. Besides which, if you're running
        a program in debug mode, you're DEBUGGING... "normal" does not apply.
        You're being rather presumptuous... you don't even know how my program
        is being used.
        Then in the modules that wanted to use it, I did:

        from debug import DEBUG, dprint
        But I got some weird behavior. The imported copy
        >
        It's not a copy.
        Actually, I'm pretty sure it is; i.e. there are two copies of the
        name: one in the namespace of the module, and one in the namespace of
        the file into which I imported it. At the time they are created, they
        both point to the same object. Is that not the very definition of a
        copy? The object itself may exist only in one place, but it has two
        names; one in each namespace.
        of DEBUG is
        read-only;
        >
        It's not read-only.
        The *object* very much is: it is immutable. The name of that object
        is DEBUG, and thus DEBUG is read-only. You can make DEBUG point to a
        different object by binding a different value to it, but if that value
        is of an immutable type, it will still be a read-only object.

        In the sentence I wrote, as well as in general, "DEBUG" actually
        refers to two different things: the object bound to the name, and the
        name itself. It's up to the reader to infer which sense is correct
        given the thing being said about it. It just so happens that the
        English sentence I wrote refers to both simultaneously.
        Just use a fully qualified name, so you dont make DEBUG local:
        >
        import debug
        print debug.DEBUG
        debug.DEBUG = True
        print debug.DEBUG
        Right, several people have already pointed this out. Which leads me
        to believe that the point of your reply was to berate me into
        following your conventions, which I have no interest in doing, in part
        because they are counterproducti ve to my goals, and in part because
        they are counter to the way I've been programming for 25 years.
        Fortunately, it's not your call how I write my code.
        Now note that ALL_UPPER names are - by convention - considered
        'constants'. If this is supposed to be altered, don't write it ALL_UPPER.
        YOUR convention, not mine.
        Also and FWIW, Python has a logging module in it's stdlib. Please use it
        instead of any half-backed squared-wheel homegrown solution.
        Note that the correct possessive form of "it" is "its" with no
        apostrophe. This was the only thing of value which you contributed,
        though really, using that is way overkill for my needs. If I've
        written bad code, by all means, please correct it. If I've written
        code in a style that you happen not to like, please feel free to keep
        that to yourself.
        My 2 cents
        Must be Zimbabwe currency...

        --
        Derek D. Martin

        GPG Key ID: 0x81CFE75D


        -----BEGIN PGP SIGNATURE-----
        Version: GnuPG v1.2.1 (GNU/Linux)

        iD8DBQFI/POFdjdlQoHP510R Aou7AJ9mo1mV0WV 2Yj/4xuaB1X0NTfQv5g CfVUgU
        ktwvJ4Gba271o10 F0uitqjo=
        =4hzz
        -----END PGP SIGNATURE-----

        Comment

        • Steven D'Aprano

          #5
          Re: Python equivalent for C module

          On Mon, 20 Oct 2008 17:09:25 -0400, Derek Martin wrote:
          On Mon, Oct 20, 2008 at 07:29:16PM +0200, Bruno Desthuilliers wrote:
          >This should have been:
          >>
          > fprintf(STDERR, "DEBUG: %s", msg);
          >
          No, it shouldn't have. If I turn on debugging, I want the debug
          messages to go to stdout, so that they can be captured along with the
          output (of which there is almost none anyway) to clearly indicate when
          they happened.
          I agree with this: debugging messages aren't errors, and shouldn't go to
          stderr.


          [...]
          >Then in the modules that wanted to use it, I did:
          >
          >from debug import DEBUG, dprint
          >But I got some weird behavior. The imported copy
          >>
          >It's not a copy.
          >
          Actually, I'm pretty sure it is; i.e. there are two copies of the name:
          one in the namespace of the module, and one in the namespace of the file
          into which I imported it.
          Names are not first class Python objects. You can't pass a name to a
          function and say "do something to this *name*, not the object".

          (Of course you can pass a string that happens to match the name to exec,
          but that's not the same thing.)

          If you dig around in globals() or locals(), you will find strings 'DEBUG'
          and 'dprint', but they aren't "names". They're just the strings that
          represents the names, and it turns out that CPython caches many (all?)
          such strings which look like identifiers, so there probably is literally
          one and only one string 'DEBUG' no matter how many times you import the
          module.

          All of this is just splitting hairs, because you don't really mean Python
          is making a copy of the name 'DEBUG', but of the *data* that DEBUG refers
          to, namely the object True. And it turns out that True is a singleton:
          there is only ever one object True.

          But even if DEBUG was set to some other value, say [1, 2, 3, 'x'], you'd
          still be wrong, because Python promises never to copy objects unless you
          explicitly tell it to. There are a number of ways to prove this, but
          perhaps this is the simplest:

          DEBUG = [True] # a mutable list

          Now from your calling code, do this:

          from module import DEBUG
          DEBUG[0] = False # mutate the object, don't rebind the name

          At the time they are created, they both point
          to the same object. Is that not the very definition of a copy?
          No. It would be a copy if they pointed to different objects, where one
          object was a copy of the other.

          The
          object itself may exist only in one place,
          which is exactly why there is no copy. It's the same object.

          but it has two names; one in each namespace.
          >
          >of DEBUG is
          >read-only;
          >>
          >It's not read-only.
          >
          The *object* very much is: it is immutable.
          So what? The *name* DEBUG is not read-only.

          The name of that object is
          DEBUG, and thus DEBUG is read-only.
          But it clearly isn't read-only, because as you yourself point out:
          You can make DEBUG point to a
          different object by binding a different value to it

          [...]
          Right, several people have already pointed this out. Which leads me to
          believe that the point of your reply was to berate me into following
          your conventions, which I have no interest in doing, in part because
          they are counterproducti ve to my goals, and in part because they are
          counter to the way I've been programming for 25 years. Fortunately, it's
          not your call how I write my code.
          No, and it's not your call what advice people give you. If you refuse to
          follow good Pythonic advice because you prefer the way you learned
          programming a quarter century ago (before Python even existed), please go
          right ahead, but don't be surprised if people consider you a lousy Python
          programmer.

          >Now note that ALL_UPPER names are - by convention - considered
          >'constants'. If this is supposed to be altered, don't write it
          >ALL_UPPER.
          >
          YOUR convention, not mine.
          Actually it is a very common convention in Python circles. I often use it
          myself. However it's not the only one, and from time to time I use
          others. I would consider using DEBUG unusual, but not excessively so.

          >Also and FWIW, Python has a logging module in it's stdlib. Please use
          >it instead of any half-backed squared-wheel homegrown solution.
          >
          Note that the correct possessive form of "it" is "its" with no
          apostrophe. This was the only thing of value which you contributed,
          though really, using that is way overkill for my needs. If I've written
          bad code, by all means, please correct it. If I've written code in a
          style that you happen not to like, please feel free to keep that to
          yourself.
          Deary deary me... you come along here, asking noob Python questions, and
          then get shirty when people give you friendly and perfectly good answers.
          Are you trying to ensure that the next question you ask remains
          unanswered?




          --
          Steven

          Comment

          • Aaron Brady

            #6
            Re: Python equivalent for C module

            On Oct 20, 3:08 pm, u...@asus-190829777.TeleW ell.gateway (Ville M.
            Vainio) wrote:
            Bruno Desthuilliers <bdesth.quelque ch...@free.quel quepart.frwrite s:
            STDOUT is for *normal* program outputs. Debug informations,
            warnings, and all verbosity should go to STDERR.
            >
            Actually, stderr is for errors, by convention. It's rather impolite to
            dump trivial debug info to stderr, which often "alerts" the user more
            than stdout.
            snip

            Indeed. Just dump to STDTRIVIAL.

            Comment

            • Derek Martin

              #7
              Re: Python equivalent for C module

              On Mon, Oct 20, 2008 at 10:43:55PM +0000, Steven D'Aprano wrote:
              All of this is just splitting hairs,
              Indeed... :)
              because you don't really mean Python is making a copy of the name
              'DEBUG', but of the *data* that DEBUG refers to, namely the object
              True.
              Well, as long as we're having semantic discussions... If you reread
              my post, it should be clear that what you wrote above can not possibly
              be the case. If you recall, my intent was to make a copy of a means
              of accessing the value known by the name "DEBUG" contained in the
              debug module, which could be accessed from any module in the program.
              Clearly the data itself *must not* be a copy, or else what I was
              trying to do would never have worked. What I was refering to as a
              copy was in fact essentially the name, or more accurately (as regards
              my conception of purpose) a reference to the data.
              The *object* very much is: it is immutable.
              >
              So what? The *name* DEBUG is not read-only.
              You may have missed where I explained that the name refers to two
              different things, and that I, speaking in loose terms, was refering to
              both things simultaneously but in different contexts. I was speaking
              loosely -- I was using "read-only" as a figure of speech of sorts, and
              elaborated *correctly* what actually happens. Again, if you reread
              my original post with that explanation in mind, I think you'll find
              that this is the only sensible interpretation for what I wrote.
              Actually it is a very common convention in Python circles. I often use it
              myself. However it's not the only one, and from time to time I use
              others. I would consider using DEBUG unusual, but not excessively so.
              To be honest, same here. My post contained throw-away C code that I
              typed up on the fly, and the same goes for the Python -- I simply
              translated the C code literally, so to speak. As has been pointed out
              in a different thread (by Bruno himself, if I'm not mistaken), the
              code hastily posted here need not represent the code that one would
              write in "real" programs. But I find it offensive that certain people
              here can't resist lambasting some posters who have simple questions,
              because the code they posted isn't up to their particular favorite
              coding "standards" (i.e. conventions), and I will speak out about it,
              especially when it's done to me. I didn't ask about coding
              conventions, but Bruno's response was roughly 75% about how my code
              sucks, and maybe 25% about answering my question. And what part did
              answer my question was completely redundant. It was roughly 95% a
              waste of time and energy for both him and me, though I did learn about
              the logging module...
              Deary deary me... you come along here, asking noob Python questions, and
              then get shirty when people give you friendly and perfectly good answers.
              Well, we disagree that the answer Bruno provided was either friendly
              or perfectly good. I did receive perfectly good answers, and if you
              read the whole thread, you saw me accept such answers graciously.
              Bruno's answer smacked of a superiority and arrogance that is not
              uncommon among certain frequent posters. He has no idea what my
              program does, or what my real code looks like, but apparently deigns
              himself the Code Police, and finds it necessary to punnish people for
              posting code which does not conform to his idea of Programming Law.

              I can't deny that I should have been able to answer my own question
              with only a few more moments thought... Though I don't think it's
              quite right to characterize questions about scope as "noob" questions.
              I suspect actual noobs don't yet know enough to ask such questions.
              Are you trying to ensure that the next question you ask remains
              unanswered?
              Not at all, just trying to preempt the pound of attitude that often
              goes with the ounce of answers. But if the choice is between no
              answer, and an answer that barely manages to avoid calling me an idiot
              (especially over coding style), I'd rather have no answer.

              --
              Derek D. Martin

              GPG Key ID: 0x81CFE75D


              -----BEGIN PGP SIGNATURE-----
              Version: GnuPG v1.2.1 (GNU/Linux)

              iD8DBQFI/VrodjdlQoHP510R AlP0AKCVY28QZEx TJ3+epEepD9k0UP 13PwCcD0Jl
              4HsvU97JMRcBpKu AOSoCCwQ=
              =lHMm
              -----END PGP SIGNATURE-----

              Comment

              • Vinay Sajip

                #8
                Re: Python equivalent for C module

                On Oct 20, 9:08 pm, u...@asus-190829777.TeleW ell.gateway (Ville M.
                Vainio) wrote:
                Unfortunately these square-wheeled homegrown solutions are easier to
                grok than the standardlogging module. It seems to target more
                "serious" applications at the cost of feeling a bit too clunky for
                quick hack jobs.
                I'm surprised to hear you say that. All you need is

                import logging

                logging.warning ("Message with %s data", "variable") # or debug, info,
                error

                and I'd like to know what simpler interface you think would be better/
                easier to grok for quick hack jobs.

                Regards,

                Vinay Sajip

                Comment

                • Ville M. Vainio

                  #9
                  Re: Python equivalent for C module

                  Vinay Sajip <vinay_sajip@ya hoo.co.ukwrites :
                  import logging
                  >
                  logging.warning ("Message with %s data", "variable") # or debug, info,
                  error
                  >
                  and I'd like to know what simpler interface you think would be better/
                  easier to grok for quick hack jobs.
                  It's not the logging itself that is a problem, it's setting up the
                  loggers that was nontrivial (back in the day I last tried it).

                  Some googling revealed what was my problem back in 2004:



                  I do realize the technical problems of coming up with
                  one-size-fits-all solution for a problem domain like this.

                  Comment

                  Working...